views:

99

answers:

2

Hi I was investigating the performance hit of creating Cachedependency objects, so I wrote a very simple test program as follows:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Web.Caching;

namespace Test
{
    internal class Program
    {
        private static readonly string[] keys = new[] {"Abc"};
        private static readonly int MaxIteration = 10000000;

        private static void Main(string[] args)
        {
            Debug.Print("first set");
            test7();
            test6();
            test5();
            test4();
            test3();
            test2();
            Debug.Print("second set");
            test2();
            test3();
            test4();
            test5();
            test6();
            test7();
        }

        private static void test2()
        {
            DateTime start = DateTime.Now;
            var list = new List<CacheDependency>();
            for (int i = 0; i < MaxIteration; i++)
            {
                list.Add(new CacheDependency(null, keys));
            }

            Debug.Print("test2 Time: " + (DateTime.Now - start));
        }

        private static void test3()
        {
            DateTime start = DateTime.Now;
            var list = new List<Func<CacheDependency>>();
            for (int i = 0; i < MaxIteration; i++)
            {
                list.Add(() => new CacheDependency(null, keys));
            }

            Debug.Print("test3 Time: " + (DateTime.Now - start));
        }

        private static void test4()
        {
            var p = new Program();
            DateTime start = DateTime.Now;
            var list = new List<Func<CacheDependency>>();
            for (int i = 0; i < MaxIteration; i++)
            {
                list.Add(p.GetDep);
            }

            Debug.Print("test4 Time: " + (DateTime.Now - start));
        }

        private static void test5()
        {
            var p = new Program();
            DateTime start = DateTime.Now;
            var list = new List<Func<CacheDependency>>();
            for (int i = 0; i < MaxIteration; i++)
            {
                list.Add(() => { return p.GetDep(); });
            }

            Debug.Print("test5 Time: " + (DateTime.Now - start));
        }

        private static void test6()
        {
            DateTime start = DateTime.Now;
            var list = new List<Func<CacheDependency>>();
            for (int i = 0; i < MaxIteration; i++)
            {
                list.Add(GetDepSatic);
            }

            Debug.Print("test6 Time: " + (DateTime.Now - start));
        }

        private static void test7()
        {
            DateTime start = DateTime.Now;
            var list = new List<Func<CacheDependency>>();
            for (int i = 0; i < MaxIteration; i++)
            {
                list.Add(() => { return GetDepSatic(); });
            }

            Debug.Print("test7 Time: " + (DateTime.Now - start));
        }

        private CacheDependency GetDep()
        {
            return new CacheDependency(null, keys);
        }

        private static CacheDependency GetDepSatic()
        {
            return new CacheDependency(null, keys);
        }
    }
}

But I can't understand why these result looks like this:

first set
test7 Time: 00:00:00.4840277
test6 Time: 00:00:02.2041261
test5 Time: 00:00:00.1910109
test4 Time: 00:00:03.1401796
test3 Time: 00:00:00.1820105
test2 Time: 00:00:08.5394884
second set
test2 Time: 00:00:07.7324423
test3 Time: 00:00:00.1830105
test4 Time: 00:00:02.3561347
test5 Time: 00:00:00.1750100
test6 Time: 00:00:03.2941884
test7 Time: 00:00:00.1850106

In particular:

  1. Why is test4 and test6 much slower than their delegate version? I also noticed that Resharper specifically has a comment on the delegate version suggesting change test5 and test7 to "Covert to method group". Which is the same as test4 and test6 but they're actually slower?
  2. I don't seem a consistent performance difference when calling test4 and test6, shouldn't static calls to be always faster?
+1  A: 

I haven't looked too far into your code, but first step would be to switch things over to use the StopWatch class instead of DateTime.Now etc.

http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx

Ted
+1  A: 

That is quite interesting. I'm wondering if your million entry lists aren't causing a garbage collection and skewing your results. Try changing the order these functions are called in and see what the results give you.

Another thing is that the JIT might have optimised your code to not create the lambda each time and is just inserting the same value over and over. Might be worth running ildasm over it and see what is actually generated.

Phil Bennett