dimanche 10 juin 2018

Sort by Reflection faster then by Member?

There are a lot of warnings regarding the speed of using Reflection in .Net. For sorting a datagridview by column Datapropertyname I made a short test program which shows Linq Sort by Reflection is faster then by Member. I am not sure if I all have done correctly and ask the community for a review.

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
    */
}

The Average is always around 10% faster when using Reflection.





Aucun commentaire:

Enregistrer un commentaire