c# – 为什么JIT_MethodAccessAllowedBySecurity需要这么多时间?

前端之家收集整理的这篇文章主要介绍了c# – 为什么JIT_MethodAccessAllowedBySecurity需要这么多时间?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用一个C#应用程序,允许用户基本上导入数据表,然后以迷你语言输入自己的公式,从基础数据计算新的列.

这些公式被编译为引擎中的LINQ表达式树,然后.NET 4.0表达式树库可能会编译为IL,因此可以执行它们.

我们最近已经开始使用我们的引擎进行一些大批量滴答数据,我们发现这些编译表达式树的速度是一个真正的瓶颈 – 当快速重新计算所有这些列时,速度相当缓慢.使用内置的Visual Studio 2010分析器来显示它,其中一半的执行时间花在clr.dll中,在一个名为JIT_MethodAccessAllowedBySecurity的方法中.

这个字符串的粗略的搜索没有产生任何东西,所以我想知道有没有人可以告诉我这种方法是什么,以及是否有办法让它不要吃掉我所有的周期?也许有一种方法可以编译这个代码,明确地给它权限做任何它想要的,以便clr可以阻止这些检查?也许由表达式树引擎生成的临时程序集没有完全信任?

无论如何,我几乎感到失落,如果有任何其他StackOverflowers在过去遇到这个问题,我很有兴趣.提前致谢!

解决方法

解决方案是使用 LambdaExpression.CompileToMethod(MethodBuilder method)而不是 LambdaExpression.Compile().

我认为Jethro当时认为CAS涉及到了正确的轨道.在测试中,当我使用表达式树来调用生成的程序集中未动态定义的函数(即使用Expression.Call来调用方法而不是一段生成代码)时,分析器才开始显示对JIT_MethodAccessAllowedBySecurity的调用.表明减缓是由CAS检查我生成代码是否可以访问正在调用方法引起的.看来,通过对我想要调用函数应用声明式安全修改,我可以避免这种开销.

不幸的是,我无法通过使用声明性安全性(PermissionSet,SecurityAction.LinkDemand等)来摆脱JIT_MethodAccessAllowedBySecurity开销.有一点我在项目中标注了[PermissionSet(SecurityAction.LinkDemand,Unrestricted = true)]的所有方法,没有任何结果.

幸运的是,当寻找向生成的代理添加属性方法时,我偶然发现了解决方案 – 使用MethodBuilder来编译表达式树而不是内置的LambdaExpression.Compile方法.

我已经包含了代替.Compile()的代码,并导致在计算引擎中消除了JIT_MethodAccessAllowedBySecurity调用和一个> 2x speedup:

// T must be of delegate type (Func<T>,Func<T1,T2>,etc.)
public static T GetCompiledDelegate<T>(Expression<T> expr)
{
    var assemblyName = new AssemblyName("DelegateHostAssembly") { Version = new Version("1.0.0.0") };

    var assemblyBuilder = 
        AppDomain.CurrentDomain.DefineDynamicAssembly(
            assemblyName,AssemblyBuilderAccess.RunAndSave);
    var moduleBuilder = assemblyBuilder.DefineDynamicModule("DelegateHostAssembly","DelegateHostAssembly.dll");
    var typeBuilder = moduleBuilder.DefineType("DelegateHostAssembly." + "foo",TypeAttributes.Public);
    var methBldr = typeBuilder.DefineMethod("Execute",MethodAttributes.Public | MethodAttributes.Static);

    expr.CompileToMethod(methBldr);

    Type myType = typeBuilder.CreateType();

    var mi = myType.GetMethod("Execute");

    // have to Box to object because .NET doesn't allow Delegates as generic constraints,// nor does it allow casting of Delegates to generic type variables like "T"
    object foo = Delegate.CreateDelegate(typeof(T),mi);

    return (T)foo;
}

当使用任何使用表达式树来调用不是由Expression tree定义的函数代码时,这个代码一直保持> 2倍.感谢大家的帮助,我希望这可以节省别人一些周期.

猜你在找的C#相关文章