Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 按反射排序比按成员排序快?_C#_Performance_List_Sorting_Reflection - Fatal编程技术网

C# 按反射排序比按成员排序快?

C# 按反射排序比按成员排序快?,c#,performance,list,sorting,reflection,C#,Performance,List,Sorting,Reflection,关于在.Net中使用反射的速度有很多警告。 为了按列Datapropertyname对datagridview进行排序,我编写了一个简短的测试程序,它显示Linq按反射排序比按成员排序快。 我不确定我是否都做得正确,并要求社区进行审查 class Program { private static Random random = new Random(); class TestClass { public string Name { get; set; }

关于在.Net中使用反射的速度有很多警告。 为了按列Datapropertyname对datagridview进行排序,我编写了一个简短的测试程序,它显示Linq按反射排序比按成员排序快。 我不确定我是否都做得正确,并要求社区进行审查

class Program {

    private static Random random = new Random();

    class TestClass {
        public string Name { get; set; }
        public int Number { get; set; }
    }


     static string RandomString(int length) {
        const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        return new string(Enumerable.Repeat(chars, length)
          .Select(s => s[random.Next(s.Length)]).ToArray());
    }


    static void SortyByReflection(List<TestClass> testlst) {
        PropertyInfo prop = typeof(TestClass).GetProperties().Where(p => p.Name == "Name").FirstOrDefault();
        List<TestClass> sorted = testlst.OrderBy(o => prop.GetValue(o)).ToList();
    }

    static void SortByMember(List<TestClass> testlst) {
        List<TestClass> sorted = testlst.OrderBy(o => o.Name).ToList();
    }


    delegate void dRunner(List<TestClass> testlst);

    static long UsedTime(dRunner testDelegate, List<TestClass> testlst) {
        Stopwatch timer = new Stopwatch();
        timer.Start();
        testDelegate(testlst);
        timer.Stop();
        return timer.ElapsedTicks;
    }

    static void Main(string[] args) {
        // make a dry run to init the program
        SortByMember(new List<TestClass>());
        SortyByReflection(new List<TestClass>());


        List<int> lstSize = new List<int> { 100, 1000, 10000, 100000 };
        foreach (int count in lstSize) {
            // Init List
            List<TestClass> testlst = new List<TestClass>();
            for (int i = 0; i < count; i++) {
                testlst.Add(new TestClass { Name = RandomString(10), Number = i });
            }
            List<long> reflection = new List<long>();
            List<long> memberTime = new List<long>();
            for (int i = 0; i < 100; i++) {
                reflection.Add(UsedTime(SortyByReflection,testlst));
                memberTime.Add(UsedTime(SortByMember,testlst));
            }
            Console.WriteLine($"{reflection.Min()} / {reflection.Max()} / {reflection.Average()} Min/ Max / Average Ticks needed for Reflection {count} size");
            Console.WriteLine($"{memberTime.Min()} / {memberTime.Max()} / {memberTime.Average()} Min/ Max / Average Ticks needed for Member {count} size");
            Console.WriteLine(new string('-', 80));
        }
        Console.WriteLine("done");
        Console.ReadLine();
    }
    /*
     * Sample output
        425 / 1837 / 539,75 Min/ Max / Average Ticks needed for Reflection 100 size
        479 / 1265 / 605,14 Min/ Max / Average Ticks needed for Member 100 size
        --------------------------------------------------------------------------------
        6251 / 11819 / 7309,82 Min/ Max / Average Ticks needed for Reflection 1000 size
        7164 / 13369 / 8201,42 Min/ Max / Average Ticks needed for Member 1000 size
        --------------------------------------------------------------------------------
        76214 / 103169 / 82003,53 Min/ Max / Average Ticks needed for Reflection 10000 size
        86139 / 121152 / 93201,55 Min/ Max / Average Ticks needed for Member 10000 size
        --------------------------------------------------------------------------------
        1092454 / 1188244 / 1139228,26 Min/ Max / Average Ticks needed for Reflection 100000 size
        1225469 / 1353753 / 1280549,37 Min/ Max / Average Ticks needed for Member 100000 size
        --------------------------------------------------------------------------------
        done
    */
}
对于这些文件,这里是新的源代码

  class Program {

    private static Random random = new Random();

    class TestClass {
        public string Name { get; set; }
        public int Number { get; set; }
    }


     static string RandomString(int length) {
        const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        return new string(Enumerable.Repeat(chars, length)
          .Select(s => s[random.Next(s.Length)]).ToArray());
    }


    static List<TestClass> SortyByReflection(List<TestClass> testlst) {
        PropertyInfo prop = typeof(TestClass).GetProperties().Where(p => p.Name == "Number").FirstOrDefault();
        List<TestClass> sorted = testlst.OrderBy(o => prop.GetValue(o)).ToList();
        return sorted;
    }

    static  List<TestClass> SortByMember(List<TestClass> testlst) {
        List<TestClass> sorted = testlst.OrderBy(o => o.Number).ToList();
        return sorted;
    }


    delegate List<TestClass> dRunner(List<TestClass> testlst);

    static List<TestClass> UsedTime(dRunner testDelegate, List<TestClass> testlst,out long time) {
        time = 0;
        Stopwatch timer = new Stopwatch();
        timer.Start();
        var x = testDelegate(testlst);
        timer.Stop();
        time = timer.ElapsedTicks;
        return x;
    }

    static void Main(string[] args) {


        // make a dry run to init the program
        SortByMember(new List<TestClass>());
        SortyByReflection(new List<TestClass>());


        List<int> lstSize = new List<int> { 100, 1000, 10000, 100000 };
        foreach (int count in lstSize) {
            // Init List
            List<TestClass> testlst = new List<TestClass>();
            for (int i = 0; i < count; i++) {
                testlst.Add(new TestClass { Name = RandomString(10), Number = i });
            }
            List<long> reflection = new List<long>();
            List<long> memberTime = new List<long>();
            for (int i = 0; i < 100; i++) {
                foreach (var lst in UsedTime(SortyByReflection,testlst,out long time)){
                    var tmp = lst.Name;
                    tmp += lst.Number.ToString();
                    reflection.Add(time);
                }
                foreach (var lst in UsedTime(SortByMember, testlst, out long time)) {
                    var tmp = lst.Name;
                    tmp += lst.Number.ToString();
                    memberTime.Add(time);
                }

            }
            Console.WriteLine($"{reflection.Min()} / {reflection.Max()} / {reflection.Average()} Min/ Max / Average Ticks needed for Reflection {count} size");
            Console.WriteLine($"{memberTime.Min()} / {memberTime.Max()} / {memberTime.Average()} Min/ Max / Average Ticks needed for Member {count} size");
            Console.WriteLine(new string('-', 80));
        }
        Console.WriteLine("done");
        Console.ReadLine();
    }
    /*
        97 / 1266 / 129,67 Min/ Max / Average Ticks needed for Reflection 100 size
        19 / 265 / 28,34 Min/ Max / Average Ticks needed for Member 100 size
        --------------------------------------------------------------------------------
        1064 / 2369 / 1357,42 Min/ Max / Average Ticks needed for Reflection 1000 size
        218 / 598 / 290,43 Min/ Max / Average Ticks needed for Member 1000 size
        --------------------------------------------------------------------------------
        12407 / 27326 / 15779,35 Min/ Max / Average Ticks needed for Reflection 10000 size
        2703 / 5100 / 3366,52 Min/ Max / Average Ticks needed for Member 10000 size
        --------------------------------------------------------------------------------
        147184 / 198677 / 160490,02 Min/ Max / Average Ticks needed for Reflection 100000 size
        35333 / 45620 / 38493,46 Min/ Max / Average Ticks needed for Member 100000 size
        --------------------------------------------------------------------------------
    */
}
类程序{
私有静态随机=新随机();
类TestClass{
公共字符串名称{get;set;}
公共整数{get;set;}
}
静态字符串随机字符串(整数长度){
常量字符串chars=“abcdefghijklmnopqrstuvwxyz012456789”;
返回新字符串(可枚举。重复(字符,长度)
.Select(s=>s[random.Next(s.Length)]).ToArray();
}
静态列表SortyByReflection(列表testlst){
PropertyInfo prop=typeof(TestClass).GetProperties()。其中(p=>p.Name==“Number”).FirstOrDefault();
List sorted=testlst.OrderBy(o=>prop.GetValue(o)).ToList();
返回排序;
}
静态列表排序成员(列表testlst){
List sorted=testlst.OrderBy(o=>o.Number.ToList();
返回排序;
}
代表列表dRunner(列表testlst);
静态列表使用时间(dRunner testDelegate、列表testlst、超时){
时间=0;
秒表计时器=新秒表();
timer.Start();
var x=testDelegate(testlst);
timer.Stop();
时间=timer.ElapsedTicks;
返回x;
}
静态void Main(字符串[]参数){
//进行试运行以初始化程序
SortByMember(新列表());
SortyByReflection(新列表());
List lstSize=新列表{100,1000,10000,100000};
foreach(以lstSize为单位的整数计数){
//初始化列表
List testlst=新列表();
for(int i=0;i
我第一次看到这篇文章时,我不像其他评论者那样信任它

但是在我自己做了消除潜在GC和JIT影响的测试之后,我可以确认声明是正确的,
SortyByReflection
方法确实比
SortByMember
平均速度更快

然而,这与反思无关

毕竟,
Enumerable.OrderBy
方法执行O(N)选择器调用(即反射与您试图度量的直接属性访问)和平均O(N*Log2(N))比较,因此时间复杂度由比较操作实现决定

这就是区别。反射方法使用的是
Comparer.Default
,而另一种方法使用的是
Comparer.Default
。令人惊讶的是,由于一些未知的原因,对于
string
s,前者比后者更快。我还没有测试过其他数据类型(最有可能是
int
和其他值类型,由于第一种情况中涉及到装箱,图片将与此相反),但是
string
就是这种情况。我已经检查了比较器实现的参考源,并了解了可能的原因,但这超出了当前问题的范围

重要的是,
OrderBy
不适合测试反射和直接访问性能。如果将第一个方法选择器更改为
o=>(string)prop.GetValue(o)
,并保持第二个方法选择器不变,或者将第二个选择器更改为
o=>(object)o.Name
并保持第一个方法选择器不变,则运行测试将显示直接访问速度比预期的反射速度快,但由于比较时间的支配,尤其是对于较大的
N

A,情况并非如此
  class Program {

    private static Random random = new Random();

    class TestClass {
        public string Name { get; set; }
        public int Number { get; set; }
    }


     static string RandomString(int length) {
        const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        return new string(Enumerable.Repeat(chars, length)
          .Select(s => s[random.Next(s.Length)]).ToArray());
    }


    static List<TestClass> SortyByReflection(List<TestClass> testlst) {
        PropertyInfo prop = typeof(TestClass).GetProperties().Where(p => p.Name == "Number").FirstOrDefault();
        List<TestClass> sorted = testlst.OrderBy(o => prop.GetValue(o)).ToList();
        return sorted;
    }

    static  List<TestClass> SortByMember(List<TestClass> testlst) {
        List<TestClass> sorted = testlst.OrderBy(o => o.Number).ToList();
        return sorted;
    }


    delegate List<TestClass> dRunner(List<TestClass> testlst);

    static List<TestClass> UsedTime(dRunner testDelegate, List<TestClass> testlst,out long time) {
        time = 0;
        Stopwatch timer = new Stopwatch();
        timer.Start();
        var x = testDelegate(testlst);
        timer.Stop();
        time = timer.ElapsedTicks;
        return x;
    }

    static void Main(string[] args) {


        // make a dry run to init the program
        SortByMember(new List<TestClass>());
        SortyByReflection(new List<TestClass>());


        List<int> lstSize = new List<int> { 100, 1000, 10000, 100000 };
        foreach (int count in lstSize) {
            // Init List
            List<TestClass> testlst = new List<TestClass>();
            for (int i = 0; i < count; i++) {
                testlst.Add(new TestClass { Name = RandomString(10), Number = i });
            }
            List<long> reflection = new List<long>();
            List<long> memberTime = new List<long>();
            for (int i = 0; i < 100; i++) {
                foreach (var lst in UsedTime(SortyByReflection,testlst,out long time)){
                    var tmp = lst.Name;
                    tmp += lst.Number.ToString();
                    reflection.Add(time);
                }
                foreach (var lst in UsedTime(SortByMember, testlst, out long time)) {
                    var tmp = lst.Name;
                    tmp += lst.Number.ToString();
                    memberTime.Add(time);
                }

            }
            Console.WriteLine($"{reflection.Min()} / {reflection.Max()} / {reflection.Average()} Min/ Max / Average Ticks needed for Reflection {count} size");
            Console.WriteLine($"{memberTime.Min()} / {memberTime.Max()} / {memberTime.Average()} Min/ Max / Average Ticks needed for Member {count} size");
            Console.WriteLine(new string('-', 80));
        }
        Console.WriteLine("done");
        Console.ReadLine();
    }
    /*
        97 / 1266 / 129,67 Min/ Max / Average Ticks needed for Reflection 100 size
        19 / 265 / 28,34 Min/ Max / Average Ticks needed for Member 100 size
        --------------------------------------------------------------------------------
        1064 / 2369 / 1357,42 Min/ Max / Average Ticks needed for Reflection 1000 size
        218 / 598 / 290,43 Min/ Max / Average Ticks needed for Member 1000 size
        --------------------------------------------------------------------------------
        12407 / 27326 / 15779,35 Min/ Max / Average Ticks needed for Reflection 10000 size
        2703 / 5100 / 3366,52 Min/ Max / Average Ticks needed for Member 10000 size
        --------------------------------------------------------------------------------
        147184 / 198677 / 160490,02 Min/ Max / Average Ticks needed for Reflection 100000 size
        35333 / 45620 / 38493,46 Min/ Max / Average Ticks needed for Member 100000 size
        --------------------------------------------------------------------------------
    */
}