A Fast Alternative to MethodInfo.Invoke

Not surprisingly, calls to MethodInfo.Invoke are slow for the same reasons outlined that were outlined in A Fast Alternative to Activator.CreateObject.

The same approach can be used to generate methods that will invoke the MethodInfo instance, but provide an amazing performance boost by handling validation up front once rather than upon every invocation.

            public static Func<TTarget, TResult> GenerateFastInvoker<TTarget, TResult>(MethodInfo method)
            {
                #if DEBUG
                    ParameterExpression targetExpression = Expression.Parameter(typeof(TTarget), "target");
                #else
                    ParameterExpression targetExpression = Expression.Parameter(typeof(TTarget));
                #endif

                Expression<Func<TTarget, TResult>> expression = Expression.Lambda<Func<TTarget, TResult>>(
                    Expression.Call(
                        targetExpression,
                        method),
                    targetExpression);
                Func<TTarget, TResult> functor = expression.Compile();
                return functor;
            }
          

The same caveats apply as before, but the performance increase is well worth it. Further, the same alterations used to create weakly-typed fast activators can be applied to generate weakly-typed fast invokers.


Project Euler - Problem 006

Problem 6 is really easy to solve without needing any new extension methods nor complicated LINQ.

              private static BigInteger GetAnswerToProblem6()
              {
                  // Get the range of numbers to process for the problem.
                  IEnumerable<BigInteger> range = BigInteger.One.To(100);
                  // Determine the square of the sum of the values within the problem space.
                  BigInteger squareOfSum = BigInteger.Pow(range.Sum(), 2);
                  // Determine the sum of the squares of the values within the problem space.
                  BigInteger sumOfSquares = range.Select(bi => BigInteger.Pow(bi, 2)).Sum();
                  // Return the different.
                  return squareOfSum - sumOfSquares;
              }
          

Project Euler - Problem 005

Problem 5 can be quickly solved using LINQ's Aggregate method and BigInteger methods.

              private static BigInteger GetAnswerToProblem5()
              {
                  BigInteger result = BigInteger.One.To(20).Aggregate(SmallestMultiplier);
                  return result;
              }
              private static BigInteger SmallestMultiplier(BigInteger current, BigInteger next)
              {
                  return current * (next / BigInteger.GreatestCommonDivisor(current, next));
              }
          

This works because at each step of the aggregation, we compute the smallest value divisible by all items in the sequence to that point. The current parameter is the smallest value for all of the previous values in the sequence, and the next is the next value in the sequence.


A Fast Alternative to Activator.CreateObject

I'm working on performance issues and tracked down a place where the code repeatedly instantiating objects via Activator.CreateInstance. The use case doesn't allow for me to change that behavior - the instances must be created. So, I need a faster alternative. Jon Skeet wrote an excellent article titled Making reflection fly and exploring delegates that discusses in depth as well as various alternatives.

Basically, by generating a method I incur the costs of evaluation once, rather than repeatedly like Activator.CreateInstance.

I know the types of parameters I need to use at compile-time, but actual type instantiated is not known until runtime. But I can generate a method at runtime to do the instantiation for me. Better still I can use LINQ expressions to generate that method and not have to emit raw IL.

            public static class FastActivator
            {
                public static Func<T1, TResult> Generate<T1, TResult>()
                {
                    ConstructorInfo constructorInfo = typeof(TResult).GetConstructor(new Type[] { typeof(T1), });

                    #if DEBUG
                        ParameterInfo[] parameters = constructorInfo.GetParameters();
                        ParameterExpression parameterExpression = Expression.Parameter(typeof(T1), parameters[0].Name);
                    #else
                        ParameterExpression parameterExpression = Expression.Parameter(typeof(T1));
                    #endif

                    Expression<Func<T1, TResult>> expression = Expression.Lambda<Func<T1, TResult>>(
                        Expression.New(
                            constructorInfo,
                            parameterExpression),
                        parameterExpression);
                    Func<T1, TResult> functor = expression.Compile();
                    return functor;
                }
            }
          

The code is for a simple case - instanting a type via a constructor that accepts a single argument. But I can easily add additional overrides to handle constructors that accept more parameters.

The preprocessor directives in the middle just make it a little easier to debug. When building in a configuration specifying the DEBUG flag, I will get parameters with names that I can use when looking over an Expression's DebugView property. In a build that does not have the flag, I can skip over that unnecessary information.

So now we have a different problem. I have a strongly typed Func<,> that I can't really use since the resultant type isn't known at compile time. So let's create a weakly typed variant that will do the same work and be in a form that will allow me reference the delegate and cache it.

            public static class WeakFastActivator
            {
                public static Func<object, object> Generate(Type resultantType, Type parameterType)
                {
                    ConstructorInfo constructorInfo = resultantType.GetConstructor(new Type[] { parameterType, });

                    #if DEBUG
                        ParameterInfo[] parameters = constructorInfo.GetParameters();
                        ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "boxed_" + parameters[0].Name);
                    #else
                        ParameterExpression parameterExpression = Expression.Parameter(typeof(object));
                    #endif

                    Expression<Func<object, object>> expression = Expression.Lambda<Func<object, object>>(
                        Expression.Block(
                            Expression.IfThen(
                                Expression.Not(Expression.TypeIs(parameterExpression, parameterType)),
                                Expression.Throw(Expression.Constant(new ArgumentException("Parameter type mismatch.", parameterExpression.Name)))),
                            Expression.Convert(
                                Expression.New(
                                    constructorInfo,
                                    Expression.Convert(parameterExpression, parameterType)),
                                resultType)),
                        parameterExpression);
                    Func<object, object> functor = expression.Compile();
                    return functor;
                }
            }
          

Now I have a method that I can use. I can store it away in a private member and invoke it repeatly to instantiate the objects I need. The weakly-typed variant includes some parameter checking as well so we have some better information in case something goes wrong.

            public static class Program
            {
                // A contrived example of how to use the WeakFastActivator.
                public static void Main()
                {
                    Type runtimeKnownType = ...; // Some type whose constructor accepts an integer.

                    Func<object, object> weakFastActivator = 
                        WeakFastActivator.Generate(runtimeKnownType, typeof(int));

                    // Now the fast activator can be repeatedly used.
                    for(int x = 0; x < int.MaxValue; x++)
                    {
                        // This will throw an ArgumentException if we do not supply an int.
                        object instance = weakFastActivator(x);
                        // Do something with the instance here.
                    }
                }
            }
          

There are three cases we can directly test - using the Activator, using a FastActivator delegate, and invoking the constructor directly.

I have this mock object for testing:

            public sealed class Mock
            {
                private readonly int _parameter;
                public Mock(int parameter)
                {
                    this._parameter = parameter;
                }
                public int Parameter
                {
                    get { return this._parameter; }
                }
            }
          

And three test cases to evaluate:

            private static void Case1()
            {
                Type mockType = typeof(Mock);
                for (int x = 0; x < ITERATION_COUNT; x++)
                {
                    Mock mock = (Mock)Activator.CreateInstance(mockType, new object[] { x, });
                    Debug.Assert(mock.Parameter == x, "Parameter does not match the expected value.");
                }
            }

            private static void Case2()
            {
                Func<int, Mock> fastActivator = FastActivator.GenerateFastActivator<int, Mock>();
                for (int x = 0; x < ITERATION_COUNT; x++)
                {
                    Mock mock = fastActivator(x);
                    Debug.Assert(mock.Parameter == x, "Parameter does not match the expected value.");
                }
            }

            private static void Case3()
            {
                ConstructorInfo constructor = typeof(Mock).GetConstructor(new Type[] { typeof(int), });
                for (int x = 0; x < ITERATION_COUNT; x++)
                {
                    Mock mock = (Mock)constructor.Invoke(new object[] { x, });
                    Debug.Assert(mock.Parameter == x, "Parameter does not match the expected value.");
                }
            }
          

And the results of the test - these are from a Release configuration running without a debugger attached where ITERATION_COUNT = 1000. The tests have a single sample execution and then run the 1000 iterations that are timed.

Case1: 24226.428ms ticks/iteration (22459ms-29665ms; σ=688.468ms)
  Bucket # 1 (22459.000ms-23179.700ms):  17
  Bucket # 2 (23179.700ms-23900.400ms): 389
  Bucket # 3 (23900.400ms-24621.100ms): 300
  Bucket # 4 (24621.100ms-25341.800ms): 238
  Bucket # 5 (25341.800ms-26062.500ms):  45
  Bucket # 6 (26062.500ms-26783.200ms):   9
  Bucket # 7 (26783.200ms-27503.900ms):   1
  Bucket # 8 (27503.900ms-28224.600ms):   0
  Bucket # 9 (28224.600ms-28945.300ms):   0
  Bucket #10 (28945.300ms-29666.000ms):   1
Case2: 1673.090ms ticks/iteration (1305ms-9792ms; σ=585.248ms)
  Bucket # 1 (1305.000ms-2153.800ms): 964
  Bucket # 2 (2153.800ms-3002.600ms):  16
  Bucket # 3 (3002.600ms-3851.400ms):   0
  Bucket # 4 (3851.400ms-4700.200ms):  10
  Bucket # 5 (4700.200ms-5549.000ms):   4
  Bucket # 6 (5549.000ms-6397.800ms):   2
  Bucket # 7 (6397.800ms-7246.600ms):   2
  Bucket # 8 (7246.600ms-8095.400ms):   1
  Bucket # 9 (8095.400ms-8944.200ms):   0
  Bucket #10 (8944.200ms-9793.000ms):   1
Case3: 11153.252ms ticks/iteration (10115ms-14759ms; σ=565.624ms)
  Bucket # 1 (10115.000ms-10579.500ms):  26
  Bucket # 2 (10579.500ms-11044.000ms): 545
  Bucket # 3 (11044.000ms-11508.500ms): 263
  Bucket # 4 (11508.500ms-11973.000ms):  74
  Bucket # 5 (11973.000ms-12437.500ms):  47
  Bucket # 6 (12437.500ms-12902.000ms):  29
  Bucket # 7 (12902.000ms-13366.500ms):   8
  Bucket # 8 (13366.500ms-13831.000ms):   3
  Bucket # 9 (13831.000ms-14295.500ms):   1
  Bucket #10 (14295.500ms-14760.000ms):   4
          

We can see that overall, Case2 runs the fastest - having the lowest per-execution time at 1673.090ms, as well as is consistently fast with 96.4% of the executions being under 2153.800ms which clearly beats the other two approaches.

It's a bit difficult to read through, and really does seem a bit too clever for my own good, but the performance benefits are too good to be ignored.

As for solving the original performance problem, the generated method can be cached and repeatedly reused, which allows for a significant performance increase. There is a one-time cost upon the first invocation when a dynamic assembly is created and loaded, but it's well worth the cost.


Formatting a DateTime per RFC822

There doesn't seem to a be a built-in mechanism to format a DateTime instance according to RFC #822.

            /// <summary>
            /// Returns a RFC822-compliant string representing a DateTime instance.
            /// </summary>
            /// <param name="datetime">The DateTime instance to be formatted.</param>
            /// <returns>The specified datetime formatted as a RFC822 datetime string.</returns>
            /// <exception cref="System.ArgumentNullException">The parameter datetime is null.</exception>
            public static string AsRFC822String(this DateTime datetime)
            {
                if (datetime == null)
                {
                    throw new ArgumentNullException("datetime");
                }
            
                int offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Hours;
                string timeZone = "+" + offset.ToString(CultureInfo.InvariantCulture).PadLeft(2, '0');
                if (offset < 0)
                {
                    int i = offset * -1;
                    timeZone = "-" + i.ToString(CultureInfo.InvariantCulture).PadLeft(2, '0');
                }
                
                return datetime.ToString(
                    "ddd, dd MMM yyyy HH:mm:ss " + timeZone.PadRight(5, '0'),
                    CultureInfo.InvariantCulture);
            }
        

Articles

My name is Doug Jenkinson. I write and ramble on about whatever comes to mind at .

Professionally

I'm currently employed as a Software Engineer and Architect with Hyland Software in Cleveland, Ohio.

Contact

You can email me at webmaster@dougjenkinson.net.

Looking for an experienced and talented developer/analyst/programmer in the Akron or Cleveland area? Be sure to look at my résumé.