Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么安全性允许JIT_方法访问占用了这么多时间?_C#_.net_Expression Trees_Codedom - Fatal编程技术网

C# 为什么安全性允许JIT_方法访问占用了这么多时间?

C# 为什么安全性允许JIT_方法访问占用了这么多时间?,c#,.net,expression-trees,codedom,C#,.net,Expression Trees,Codedom,我正在开发一个C#应用程序,它允许用户基本上导入数据表,然后用迷你语言输入自己的公式,从底层数据计算新的列 这些公式被编译到引擎中的LINQ表达式树中,.NET4.0表达式树库随后可能会编译成IL,以便执行 最近,我们开始使用我们的引擎处理一些大容量的滴答数据,我们发现这些已编译表达式树的速度是一个真正的瓶颈——在动态重新计算所有这些列时,速度非常慢。使用内置的Visual Studio 2010探查器点击它可以发现,我们一半的执行时间都花在了clr.dll中,该方法名为JIT_MethodAc

我正在开发一个C#应用程序,它允许用户基本上导入数据表,然后用迷你语言输入自己的公式,从底层数据计算新的列

这些公式被编译到引擎中的LINQ表达式树中,.NET4.0表达式树库随后可能会编译成IL,以便执行

最近,我们开始使用我们的引擎处理一些大容量的滴答数据,我们发现这些已编译表达式树的速度是一个真正的瓶颈——在动态重新计算所有这些列时,速度非常慢。使用内置的Visual Studio 2010探查器点击它可以发现,我们一半的执行时间都花在了clr.dll中,该方法名为JIT_MethodAccessAllowedBySecurity

粗略地搜索这个字符串并没有得到任何结果,所以我想知道是否有人能告诉我这个方法是什么,是否有办法防止它吞噬我所有的周期?也许有一种方法可以编译这段代码,并显式地授予它执行任何它想要的操作的权限,这样clr就可以停止这些检查了?表达式树引擎生成的临时程序集可能没有完全信任


不管怎样,我几乎不知所措,我很想知道是否有其他堆垛机在过去遇到过这个问题。提前谢谢

我认为这与CAS(代码访问安全)有关

CAS是基于汇编的。当你编码的时候 调用受保护的方法.NET 框架运行时检查您的 程序集,以查看是否已授予 在一个或多个必需的权限上 方法。NET框架rutime 然后遍历堆栈以检查每个 在堆栈中为这些 终止。如果一个程序集没有 拥有所有必需的权限, 将引发securityexception,并且 代码正在运行

下面是我认为您的代码正在发生的情况

。。。发生堆栈遍历并删除策略 每次执行以下操作时都会执行检查: 方法被调用。这是一个特殊的问题 类中组件的问题 图书馆,可以称之为许多 时代。在这种情况下,您可以使用 链接需求,以表明 在上执行权限集检查 在链接时间作为JIT的一部分 复杂化过程。要做到这一点,你必须 通过使用 具有 值的参数
SecurityAction.LinkDemand

我希望这会有所帮助,看起来您需要做的就是设置
SecurityAction.LinkDemand
属性。引用的文本来自Microsoft.NET 2.0开发的高级基础

关于

解决方案是使用而不是

我认为Jethro认为CAS参与其中是正确的。在测试中,当我使用表达式树调用生成的程序集中未动态定义的函数(即使用expression.call调用库方法而不是生成的代码段)时,探查器才开始显示对JIT_MethodAccessAllowedBySecurity的调用这表明减速是由CAS检查生成的代码是否可以访问它正在调用的方法引起的。这样看来,通过对我希望调用的函数应用声明性安全性修改,我可以避免这种开销

不幸的是,我无法通过任何声明性安全性(PermissionSet、SecurityAction.LinkDemand等)的使用摆脱JIT_MethodAccessAllowedBySecurity开销。有一次,我的项目中的每个方法都标有[PermissionSet(SecurityAction.LinkDemand,Unrestricted=true)],但没有结果

幸运的是,在寻找向生成的委托添加属性的方法时,我偶然发现了解决方案——使用MethodBuilder编译表达式树,而不是内置的LambdaExpression.compile方法

我已经加入了一些代码,这些代码取代了.Compile(),消除了安全调用允许的JIT_方法访问,并在我们的计算引擎中实现了>2倍的加速:

// 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;
}
//T必须是委托类型(Func、Func等)
公共静态T GetCompiledDelegate(表达式表达式表达式)
{
var assemblyName=newassemblyname(“DelegateHostAssembly”){Version=new Version(“1.0.0.0”)};
变量assemblyBuilder=
AppDomain.CurrentDomain.DefinedDynamicAssembly(
汇编名,
AssemblyBuilderAccess.RunAndSave);
var moduleBuilder=assemblyBuilder.DefinedDynamicModule(“DelegateHostAssembly”、“DelegateHostAssembly.dll”);
var typeBuilder=moduleBuilder.DefineType(“DelegateHostAssembly.”+“foo”,TypeAttributes.Public);
var methBldr=typeBuilder.DefineMethod(“执行”,MethodAttributes.Public | MethodAttributes.Static);
实验方法(methBldr);
类型myType=typeBuilder.CreateType();
var mi=myType.GetMethod(“执行”);
//必须框到对象,因为.NET不允许将委托作为通用约束,
//它也不允许将委托强制转换为泛型类型变量,如“T”
object foo=Delegate.CreateDelegate(typeof(T),mi);
返回(T)foo;
}

当使用任何使用表达式树调用本身未由表达式树定义的函数的代码时,此代码的速度始终大于2倍。感谢大家的帮助,我希望这能为其他人节省一些周期。

你能发布堆栈跟踪,将你带到JIT_MethodAccessAllowedBySecurity吗?@NightAllianner-在内置VS2010探查器中,它说当我们调用编译的委托时,会发生JIT_MethodAccessAllowedBySecurity(而不是在编译委托的主体中的某个地方)。看来Jethro走上了正确的道路,我们必须找到一种方法来设置委托本身的属性。首先,感谢您的帮助,Jethro。不幸的是,SecurityAction.LinkDemand(和