zoukankan      html  css  js  c++  java
  • C# Expression 表达式树 缓存

    在学习mvc3源代码的时候,发现里面调用action的源代码如下:

    private static ActionExecutor GetExecutor(MethodInfo methodInfo) {
                // Parameters to executor
                ParameterExpression controllerParameter = Expression.Parameter(typeof(ControllerBase), "controller");
                ParameterExpression parametersParameter = Expression.Parameter(typeof(object[]), "parameters");
    
                // Build parameter list
                List<Expression> parameters = new List<Expression>();
                ParameterInfo[] paramInfos = methodInfo.GetParameters();
                for (int i = 0; i < paramInfos.Length; i++) {
                    ParameterInfo paramInfo = paramInfos[i];
                    BinaryExpression valueObj = Expression.ArrayIndex(parametersParameter, Expression.Constant(i));
                    UnaryExpression valueCast = Expression.Convert(valueObj, paramInfo.ParameterType);
    
                    // valueCast is "(Ti) parameters[i]"
                    parameters.Add(valueCast);
                }
    
                // Call method
                UnaryExpression instanceCast = (!methodInfo.IsStatic) ? Expression.Convert(controllerParameter, methodInfo.ReflectedType) : null;
                MethodCallExpression methodCall = methodCall = Expression.Call(instanceCast, methodInfo, parameters);
    
                // methodCall is "((TController) controller) method((T0) parameters[0], (T1) parameters[1], ...)"
                // Create function
                if (methodCall.Type == typeof(void)) {
                    Expression<VoidActionExecutor> lambda = Expression.Lambda<VoidActionExecutor>(methodCall, controllerParameter, parametersParameter);
                    VoidActionExecutor voidExecutor = lambda.Compile();
                    return WrapVoidAction(voidExecutor);
                }
                else {
                    // must coerce methodCall to match ActionExecutor signature
                    UnaryExpression castMethodCall = Expression.Convert(methodCall, typeof(object));
                    Expression<ActionExecutor> lambda = Expression.Lambda<ActionExecutor>(castMethodCall, controllerParameter, parametersParameter);
                    return lambda.Compile();
                }
            }
    

    里面用了表达式树,当时的我对表达式树还不怎么了解,曾提出一个疑问,为什么不用反射而要用表达式树了,在网上找了很多资料说明表达式树比反射性能要高。甚至根由大牛曾提出表达式缓存的思想,http://blog.zhaojie.me/2009/03/expression-cache-2-simple-key-cache.html。然而在mvc3中有些地方还是用了表达式树缓存的(CachedExpressionCompiler mvc3自带的)

    至于怎么缓存我这里就不班门弄斧了,只是告诉一下大家Compile()这个东东很伤性能啊。

    现在说说我的测试吧:

    static void Main(string[] args)
            {
                TestExpress(100000);
                TestExpress(500000);
                Console.ReadLine();
            }
    
            private static void TestExpress(int count)
            {
                // int count = 100000;
                Console.WriteLine("循环次数:" + count);
                Expression<Func<int, int, int>> addExpr = (x, y) => x + y;
    
                var start = DateTime.Now;
                for (int i = 0; i < count; i++)
                {
                    Func<int, int, int> test = addExpr.Compile();
                    int result = test(1, 2);
                }
                var end = DateTime.Now;
                var time = end - start;
                Console.WriteLine("no Cache:" + time.Milliseconds);
                Func<int, int, int> addResult = addExpr.Compile();
                start = DateTime.Now;
                for (int i = 0; i < count; i++)
                {
                    int result = addResult(1, 2);
                }
                end = DateTime.Now;
                time = end - start;
                Console.WriteLine("Cache:" + time.Milliseconds);
            }
    

    我在release下得到的结果:


    在每个计算机每次执行的结果都是不同的,但是缓存了时间明显要短。

    我把有关Expression表达式树缓存 Expression表达式树序列化的源代码整理了一下,方便大家下载。http://download.csdn.net/detail/dz45693/4375232

  • 相关阅读:
    梳理NLP预训练模型
    听懂NLPer说的是啥
    自然语言处理之HMM模型分词
    入门自然语言处理(NLP)的门
    js轮播图
    js中for循环this的使用
    vue-cli3的vue.config.js配置信息
    vuex的commit、payload、actions、setter、mutations等方法案例
    Vue做数据和视图原理(数据劫持)
    fetch的使用方法(基于promise方法进行增删改查)
  • 原文地址:https://www.cnblogs.com/majiang/p/2564060.html
Copyright © 2011-2022 走看看