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

  • 相关阅读:
    CHROME下去掉保存密码后输入框变成黄色背景样式
    AJAX请求遭遇未登录和Session失效的解决方案
    Oracle数据导入导出imp/exp
    缓存技术
    存储过程中引用的常规表,临时表以及表变量是否会导致存储过程的重编译
    给定一张表(列有月份,销售额),要求查询出月份、本月销售额、上月销售额这三个结果,如果当月上个月的销售额不存在就显示为“*”。
    tempdb 数据文件暴涨
    数据库还原成功之后,数据库依然处于还原状态
    CONVERT时间
    sql 2008 链接服务器到 sql 2000
  • 原文地址:https://www.cnblogs.com/majiang/p/2564060.html
Copyright © 2011-2022 走看看