惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
Jina AI
Jina AI
宝玉的分享
宝玉的分享
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
J
Java Code Geeks
博客园 - 【当耐特】
小众软件
小众软件
博客园 - Franky
S
SegmentFault 最新的问题
WordPress大学
WordPress大学
雷峰网
雷峰网
The Cloudflare Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
量子位
Last Week in AI
Last Week in AI
博客园_首页
月光博客
月光博客
IT之家
IT之家
阮一峰的网络日志
阮一峰的网络日志
Webroot Blog
Webroot Blog
Stack Overflow Blog
Stack Overflow Blog
腾讯CDC
云风的 BLOG
云风的 BLOG
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
W
WeLiveSecurity
Recent Commits to openclaw:main
Recent Commits to openclaw:main
D
Docker
The Last Watchdog
The Last Watchdog
有赞技术团队
有赞技术团队
Hacker News - Newest:
Hacker News - Newest: "LLM"
D
DataBreaches.Net
S
Security @ Cisco Blogs
Blog — PlanetScale
Blog — PlanetScale
GbyAI
GbyAI
TaoSecurity Blog
TaoSecurity Blog
S
Security Affairs
Y
Y Combinator Blog
O
OpenAI News
罗磊的独立博客
MongoDB | Blog
MongoDB | Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Forbes - Security
Forbes - Security
P
Palo Alto Networks Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
K
Kaspersky official blog
Cloudbric
Cloudbric

博客园 - 分享 共赢

大爱,netbeans的远程开发 lvs + keepalived udp小结 web项目下,甩开RazorTemplateEngine做模板处理 将watin的ui单元测试集成到cc.net 命令行发布web项目 Microsoft © SilverlightTM Release History 针对sl的ICSharpCode.SharpZipLib,只保留zip,gzip的流压缩、解压缩功能 c# 编译器优化的功劳?与泛型有关的代码的疑惑 高效获取某个数字的最后2位 centos asp.net运行环境配置 扣出MSLinqToSQLGenerator的基类,可用于开发自定义工具(custom tool) [转]我在微软做PM ... Linq to sql 简单性能差异指引 April Rosario(vs2010?) CTP now available! 手工杀毒利器 在form上设定了defaultbutton属性之后,切换提交按钮的解决办法 在form上设定了defaultbutton属性之后,切换提交按钮的解决办法 Bingo Day-展示自我,共享成功! 使用System.Net.Mail发送邮件,vs2005与vs2008存在差别?
不同IComparer对数组排序Array.Sort,Linq orderby的性能的影响
分享 共赢 · 2010-01-22 · via 博客园 - 分享 共赢

      今天很热闹啊。老赵的数组排序方法的性能比较(中):Array.Sort<T>实现分析Ivony的 数组排序LINQ的性能优势初步分析 —— 不起眼的属性等有关linq性能文章让我忍不住写下此文章。

      Ivony的提供的代码中,对数组的排序时采用自定义的PersonComparer,而linq排序使用的确是Comparer<int>.Default,代码分析如下:

      数组排序     

private static void SortWithCustomComparer(Person[] array)
 {
    Array.Sort(array, 
new PersonComparer());
}

    LINQ排序    

private static void SortWithLinq( Person[] array )
{
    var sorted 
=
        ( from person 
in array
         orderby person.ID
         select person ).ToList();
}

     上述lambda表达式对应为varsorted = Enumerable.OrderBy<Person,int>(array,person =>person.ID).ToList()。通过reflector反汇编可以得到以下代码

代码

//Enumerable类中OrderBy的代码
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
    
return new OrderedEnumerable<TSource, TKey>(source, keySelector, nullfalse);
}
//内部类OrderedEnumerable的代码
internal class OrderedEnumerable<TElement, TKey> : OrderedEnumerable<TElement>
{
    
// Fields
    internal IComparer<TKey> comparer;
    
internal bool descending;
    
internal Func<TElement, TKey> keySelector;
    
internal OrderedEnumerable<TElement> parent;// Methods
    internal OrderedEnumerable(IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending)
    {
        
if (source == null)
        {
            
throw Error.ArgumentNull("source");
        }
        
if (keySelector == null)
        {
            
throw Error.ArgumentNull("keySelector");
        }
        
base.source = source;
        
this.parent = null;
        
this.keySelector = keySelector;
        
this.comparer = (comparer != null? comparer : ((IComparer<TKey>) Comparer<TKey>.Default);
        
this.descending = descending;
    }
internal override EnumerableSorter<TElement> GetEnumerableSorter(EnumerableSorter<TElement> next)
    {
        EnumerableSorter
<TElement> enumerableSorter = new EnumerableSorter<TElement, TKey>(this.keySelector, this.comparer, this.descending, next);
        
if (this.parent != null)
        {
            enumerableSorter 
= this.parent.GetEnumerableSorter(enumerableSorter);
        }
        
return enumerableSorter;
    }
}

      在文章数组排序方法的性能比较(上):注意事项及试验,老赵测试得出的结果可以得知PersonComparer比Comparer<int>.Default排序慢。

      在增加一个新的SortWithLinq2方法之后,release运行测试,我得到新的结果。

      新代码: 

代码

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;namespace Exam11
{
    
public static class CodeTimer
    {
        
public static void Initialize()
        {
            Process.GetCurrentProcess().PriorityClass 
= ProcessPriorityClass.High;
            Thread.CurrentThread.Priority 
= ThreadPriority.Highest;
            Time(
""1, () => { });
        }
public static void Time(string name, int iteration, Action action)
        {
            
if (String.IsNullOrEmpty(name)) return;
            
// warm up            
            action();
            
// 1.           
            ConsoleColor currentForeColor = Console.ForegroundColor;
            Console.ForegroundColor 
= ConsoleColor.Yellow;
            Console.WriteLine(name);
            
// 2.          
            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
            
int[] gcCounts = new int[GC.MaxGeneration + 1];
            
for (int i = 0; i <= GC.MaxGeneration; i++)
            {
                gcCounts[i] 
= GC.CollectionCount(i);
            }
            
// 3.         
            Stopwatch watch = new Stopwatch();
            watch.Start();
            
ulong cycleCount = GetCycleCount();
            
for (int i = 0; i < iteration; i++) action();
            
ulong cpuCycles = GetCycleCount() - cycleCount;
            watch.Stop();
            
// 4.           
            Console.ForegroundColor = currentForeColor;
            Console.WriteLine(
"\tTime Elapsed:\t" + watch.ElapsedMilliseconds.ToString("N0"+ "ms");
            Console.WriteLine(
"\tCPU Cycles:\t" + cpuCycles.ToString("N0"));
            
// 5.        
            for (int i = 0; i <= GC.MaxGeneration; i++)
            {
                
int count = GC.CollectionCount(i) - gcCounts[i];
                Console.WriteLine(
"\tGen " + i + ": \t\t" + count);
            }
            Console.WriteLine();
        }
        
private static ulong GetCycleCount()
        {
            
ulong cycleCount = 0;
            QueryThreadCycleTime(GetCurrentThread(), 
ref cycleCount);
            
return cycleCount;
        }
        [DllImport(
"kernel32.dll")]
        [
return: MarshalAs(UnmanagedType.Bool)]
        
static extern bool QueryThreadCycleTime(IntPtr threadHandle, ref ulong cycleTime);
        [DllImport(
"kernel32.dll")]
        
static extern IntPtr GetCurrentThread();
    }
class Program
    {
        
static void Main(string[] args)
        {
            var random 
= new Random(DateTime.Now.Millisecond);
            var array 
= Enumerable.Repeat(050000).Select(_ => new Person { ID = random.Next() }).ToArray();

            JetBrains.dotTrace.Api.CPUProfiler.Start();

//老赵程序
            CodeTimer.Initialize();
            CodeTimer.Time(
"SortWithCustomComparer"500, () => SortWithCustomComparer(CloneArray(array)));
            CodeTimer.Time(
"SortWithLinq2"500, () => SortWithLinq(CloneArray(array)));
            CodeTimer.Time(
"SortWithLinq"500, () => SortWithLinq2(CloneArray(array)));

            JetBrains.dotTrace.Api.CPUProfiler.StopAndSaveSnapShot();                   
        }

public static void Time(string name, int iteration, Action action)
        {
            action();

            Console.WriteLine(name);

for (int i = 0; i < iteration; i++) action();
        }
private static readonly PersonComparer comparer = new PersonComparer();private static void SortWithCustomComparer(Person[] array)
        {
            Array.Sort(array, comparer);
        }
private static void SortWithLinq(Person[] array)
        {
            
//array = (from person in array
            
//         orderby person.ID
            
//         select person).ToList();
             Enumerable.OrderBy<Person,int>(array,person =>person.ID).ToList();
        }
private static void SortWithLinq2(Person[] array)
        {
            
//array = (from person in array
            
//         orderby person.ID
            
//         select person).ToList();
            Enumerable.OrderBy<Person, Person>(array, person => person, comparer).ToList();
        }
private static T[] CloneArray<T>(T[] source)
        {
            var dest 
= new T[source.Length];
            Array.Copy(source, dest, source.Length);
            
return dest;
        }

    }

public class Person
    {
        
public string FirstName
        {
            
get;
            
set;
        }
public string LastName
        {
            
get;
            
set;
        }
public int ID
        {
            
get;
            
set;
        }
public override int GetHashCode()
        {
            
return this.ID.GetHashCode();
        }
    }
public class PersonComparer : IComparer<Person>
    {
        
public int Compare(Person x, Person y)
        {
            
return x.ID - y.ID;
        }

    }
}

    不使用dottrace探测得到测试结果(使用dottrace之后运行态慢了,而且不好得到控制台的显示结果,除非使用辅助软件):

SortWithCustomComparer
        Time Elapsed:   11,446ms
        CPU Cycles:     26,201,674,700
        Gen 0:          31
        Gen 1:          31
        Gen 2:          31

SortWithLinq
        Time Elapsed:   14,970ms
        CPU Cycles:     34,259,890,929
        Gen 0:          311
        Gen 1:          310
        Gen 2:          187

SortWithLinq2
        Time Elapsed:   18,573ms
        CPU Cycles:     42,491,287,773
        Gen 0:          311
        Gen 1:          311
        Gen 2:          187 

       使用dottrace的分析图如如下(启动dottrace后程序运行的时间比之前的慢多了):

      上述结果测试表明,在使用PersonComparer之后SortWithLinq2比SortWithLinq慢了差不多一倍。在此也印证老赵的相关分析。