Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.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# 可回收动态程序集中的静态字段访问缺乏性能_C#_.net_Clr - Fatal编程技术网

C# 可回收动态程序集中的静态字段访问缺乏性能

C# 可回收动态程序集中的静态字段访问缺乏性能,c#,.net,clr,C#,.net,Clr,对于动态二进制翻译模拟器,我需要生成具有访问静态字段的类的可收集的.NET程序集。但是,当在可回收程序集中使用静态字段时,执行性能比不可回收程序集低2-3倍。这一现象在中国并不存在 不使用静态字段的可回收程序集 在下面的代码中,抽象类absrtest的方法MyMethod由可回收和不可回收的动态程序集实现。使用CreateTypeConst时,MyMethod将ulong参数值乘以两个常量值,而使用CreateTypeField时,第二个因子取自 构造函数初始化了静态字段MyField 为了获得

对于动态二进制翻译模拟器,我需要生成具有访问静态字段的类的可收集的.NET程序集。但是,当在可回收程序集中使用静态字段时,执行性能比不可回收程序集低2-3倍。这一现象在中国并不存在 不使用静态字段的可回收程序集

在下面的代码中,抽象类
absrtest
的方法
MyMethod
由可回收和不可回收的动态程序集实现。使用
CreateTypeConst
时,
MyMethod
将ulong参数值乘以两个常量值,而使用
CreateTypeField时,第二个因子取自
构造函数初始化了静态字段
MyField

为了获得真实的结果,将
MyMethod
结果累积到for循环中

以下是测量结果(.NET CLR 4.5/4.6):

Testing non-collectible const multiply:
Elapsed: 8721.2867 ms

Testing collectible const multiply:
Elapsed: 8696.8124 ms

Testing non-collectible field multiply:
Elapsed: 10151.6921 ms

Testing collectible field multiply:
Elapsed: 33404.4878 ms
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Diagnostics;

public abstract class AbstrTest {
  public abstract ulong MyMethod(ulong x);
}

public class DerivedClassBuilder {

  private static Type CreateTypeConst(string name, bool collect) {
    // Create an assembly.
    AssemblyName myAssemblyName = new AssemblyName();
    myAssemblyName.Name = name;
    AssemblyBuilder myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
       myAssemblyName, collect ? AssemblyBuilderAccess.RunAndCollect : AssemblyBuilderAccess.Run);

    // Create a dynamic module in Dynamic Assembly.
    ModuleBuilder myModuleBuilder = myAssembly.DefineDynamicModule(name);

    // Define a public class named "MyClass" in the assembly.
    TypeBuilder myTypeBuilder = myModuleBuilder.DefineType("MyClass", TypeAttributes.Public, typeof(AbstrTest));

    // Create the MyMethod method.
    MethodBuilder myMethodBuilder = myTypeBuilder.DefineMethod("MyMethod",
       MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig,
       typeof(ulong), new Type [] { typeof(ulong) });
    ILGenerator methodIL = myMethodBuilder.GetILGenerator();
    methodIL.Emit(OpCodes.Ldarg_1);
    methodIL.Emit(OpCodes.Ldc_I4_2);
    methodIL.Emit(OpCodes.Conv_U8);
    methodIL.Emit(OpCodes.Mul);
    methodIL.Emit(OpCodes.Ret);

    return myTypeBuilder.CreateType();
  }

  private static Type CreateTypeField(string name, bool collect) {
    // Create an assembly.
    AssemblyName myAssemblyName = new AssemblyName();
    myAssemblyName.Name = name;
    AssemblyBuilder myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
       myAssemblyName, collect ? AssemblyBuilderAccess.RunAndCollect : AssemblyBuilderAccess.Run);

    // Create a dynamic module in Dynamic Assembly.
    ModuleBuilder myModuleBuilder = myAssembly.DefineDynamicModule(name);

    // Define a public class named "MyClass" in the assembly.
    TypeBuilder myTypeBuilder = myModuleBuilder.DefineType("MyClass", TypeAttributes.Public, typeof(AbstrTest));

    // Define a private String field named "MyField" in the type.
    FieldBuilder myFieldBuilder = myTypeBuilder.DefineField("MyField",
       typeof(ulong), FieldAttributes.Private | FieldAttributes.Static);

    // Create the constructor.
    ConstructorBuilder constructor = myTypeBuilder.DefineConstructor(
       MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig,
       CallingConventions.Standard, Type.EmptyTypes);
    ConstructorInfo superConstructor = typeof(AbstrTest).GetConstructor(
       BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
       null, Type.EmptyTypes, null);
    ILGenerator constructorIL = constructor.GetILGenerator();
    constructorIL.Emit(OpCodes.Ldarg_0);
    constructorIL.Emit(OpCodes.Call, superConstructor);
    constructorIL.Emit(OpCodes.Ldc_I4_2);
    constructorIL.Emit(OpCodes.Conv_U8);
    constructorIL.Emit(OpCodes.Stsfld, myFieldBuilder);
    constructorIL.Emit(OpCodes.Ret);

    // Create the MyMethod method.
    MethodBuilder myMethodBuilder = myTypeBuilder.DefineMethod("MyMethod",
       MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig,
       typeof(ulong), new Type [] { typeof(ulong) });
    ILGenerator methodIL = myMethodBuilder.GetILGenerator();
    methodIL.Emit(OpCodes.Ldarg_1);
    methodIL.Emit(OpCodes.Ldsfld, myFieldBuilder);
    methodIL.Emit(OpCodes.Mul);
    methodIL.Emit(OpCodes.Ret);

    return myTypeBuilder.CreateType();
  }

  public static void Main() {
    ulong accu;
    Stopwatch stopwatch;
    try {
      Console.WriteLine("Testing non-collectible const multiply:");
      AbstrTest i0 = (AbstrTest)Activator.CreateInstance(
        CreateTypeConst("MyClassModule0", false));
      stopwatch = Stopwatch.StartNew();
      accu = 0;
      for (uint i = 0; i < 0xffffffff; i++)
        accu += i0.MyMethod(i);
      stopwatch.Stop();
      Console.WriteLine("Elapsed: " + stopwatch.Elapsed.TotalMilliseconds + " ms");

      Console.WriteLine("Testing collectible const multiply:");
      AbstrTest i1 = (AbstrTest)Activator.CreateInstance(
        CreateTypeConst("MyClassModule1", true));
      stopwatch = Stopwatch.StartNew();
      accu = 0;
      for (uint i = 0; i < 0xffffffff; i++)
        accu += i1.MyMethod(i);
      stopwatch.Stop();
      Console.WriteLine("Elapsed: " + stopwatch.Elapsed.TotalMilliseconds + " ms");

      Console.WriteLine("Testing non-collectible field multiply:");
      AbstrTest i2 = (AbstrTest)Activator.CreateInstance(
        CreateTypeField("MyClassModule2", false));
      stopwatch = Stopwatch.StartNew();
      accu = 0;
      for (uint i = 0; i < 0xffffffff; i++)
        accu += i2.MyMethod(i);
      stopwatch.Stop();
      Console.WriteLine("Elapsed: " + stopwatch.Elapsed.TotalMilliseconds + " ms");

      Console.WriteLine("Testing collectible field multiply:");
      AbstrTest i3 = (AbstrTest)Activator.CreateInstance(
        CreateTypeField("MyClassModule3", true));
      stopwatch = Stopwatch.StartNew();
      accu = 0;
      for (uint i = 0; i < 0xffffffff; i++)
        accu += i3.MyMethod(i);
      stopwatch.Stop();
      Console.WriteLine("Elapsed: " + stopwatch.Elapsed.TotalMilliseconds + " ms");
    }
    catch (Exception e) {
      Console.WriteLine("Exception Caught " + e.Message);
    }
  }
}
这是我的复制机代码:

Testing non-collectible const multiply:
Elapsed: 8721.2867 ms

Testing collectible const multiply:
Elapsed: 8696.8124 ms

Testing non-collectible field multiply:
Elapsed: 10151.6921 ms

Testing collectible field multiply:
Elapsed: 33404.4878 ms
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Diagnostics;

public abstract class AbstrTest {
  public abstract ulong MyMethod(ulong x);
}

public class DerivedClassBuilder {

  private static Type CreateTypeConst(string name, bool collect) {
    // Create an assembly.
    AssemblyName myAssemblyName = new AssemblyName();
    myAssemblyName.Name = name;
    AssemblyBuilder myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
       myAssemblyName, collect ? AssemblyBuilderAccess.RunAndCollect : AssemblyBuilderAccess.Run);

    // Create a dynamic module in Dynamic Assembly.
    ModuleBuilder myModuleBuilder = myAssembly.DefineDynamicModule(name);

    // Define a public class named "MyClass" in the assembly.
    TypeBuilder myTypeBuilder = myModuleBuilder.DefineType("MyClass", TypeAttributes.Public, typeof(AbstrTest));

    // Create the MyMethod method.
    MethodBuilder myMethodBuilder = myTypeBuilder.DefineMethod("MyMethod",
       MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig,
       typeof(ulong), new Type [] { typeof(ulong) });
    ILGenerator methodIL = myMethodBuilder.GetILGenerator();
    methodIL.Emit(OpCodes.Ldarg_1);
    methodIL.Emit(OpCodes.Ldc_I4_2);
    methodIL.Emit(OpCodes.Conv_U8);
    methodIL.Emit(OpCodes.Mul);
    methodIL.Emit(OpCodes.Ret);

    return myTypeBuilder.CreateType();
  }

  private static Type CreateTypeField(string name, bool collect) {
    // Create an assembly.
    AssemblyName myAssemblyName = new AssemblyName();
    myAssemblyName.Name = name;
    AssemblyBuilder myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
       myAssemblyName, collect ? AssemblyBuilderAccess.RunAndCollect : AssemblyBuilderAccess.Run);

    // Create a dynamic module in Dynamic Assembly.
    ModuleBuilder myModuleBuilder = myAssembly.DefineDynamicModule(name);

    // Define a public class named "MyClass" in the assembly.
    TypeBuilder myTypeBuilder = myModuleBuilder.DefineType("MyClass", TypeAttributes.Public, typeof(AbstrTest));

    // Define a private String field named "MyField" in the type.
    FieldBuilder myFieldBuilder = myTypeBuilder.DefineField("MyField",
       typeof(ulong), FieldAttributes.Private | FieldAttributes.Static);

    // Create the constructor.
    ConstructorBuilder constructor = myTypeBuilder.DefineConstructor(
       MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig,
       CallingConventions.Standard, Type.EmptyTypes);
    ConstructorInfo superConstructor = typeof(AbstrTest).GetConstructor(
       BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
       null, Type.EmptyTypes, null);
    ILGenerator constructorIL = constructor.GetILGenerator();
    constructorIL.Emit(OpCodes.Ldarg_0);
    constructorIL.Emit(OpCodes.Call, superConstructor);
    constructorIL.Emit(OpCodes.Ldc_I4_2);
    constructorIL.Emit(OpCodes.Conv_U8);
    constructorIL.Emit(OpCodes.Stsfld, myFieldBuilder);
    constructorIL.Emit(OpCodes.Ret);

    // Create the MyMethod method.
    MethodBuilder myMethodBuilder = myTypeBuilder.DefineMethod("MyMethod",
       MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig,
       typeof(ulong), new Type [] { typeof(ulong) });
    ILGenerator methodIL = myMethodBuilder.GetILGenerator();
    methodIL.Emit(OpCodes.Ldarg_1);
    methodIL.Emit(OpCodes.Ldsfld, myFieldBuilder);
    methodIL.Emit(OpCodes.Mul);
    methodIL.Emit(OpCodes.Ret);

    return myTypeBuilder.CreateType();
  }

  public static void Main() {
    ulong accu;
    Stopwatch stopwatch;
    try {
      Console.WriteLine("Testing non-collectible const multiply:");
      AbstrTest i0 = (AbstrTest)Activator.CreateInstance(
        CreateTypeConst("MyClassModule0", false));
      stopwatch = Stopwatch.StartNew();
      accu = 0;
      for (uint i = 0; i < 0xffffffff; i++)
        accu += i0.MyMethod(i);
      stopwatch.Stop();
      Console.WriteLine("Elapsed: " + stopwatch.Elapsed.TotalMilliseconds + " ms");

      Console.WriteLine("Testing collectible const multiply:");
      AbstrTest i1 = (AbstrTest)Activator.CreateInstance(
        CreateTypeConst("MyClassModule1", true));
      stopwatch = Stopwatch.StartNew();
      accu = 0;
      for (uint i = 0; i < 0xffffffff; i++)
        accu += i1.MyMethod(i);
      stopwatch.Stop();
      Console.WriteLine("Elapsed: " + stopwatch.Elapsed.TotalMilliseconds + " ms");

      Console.WriteLine("Testing non-collectible field multiply:");
      AbstrTest i2 = (AbstrTest)Activator.CreateInstance(
        CreateTypeField("MyClassModule2", false));
      stopwatch = Stopwatch.StartNew();
      accu = 0;
      for (uint i = 0; i < 0xffffffff; i++)
        accu += i2.MyMethod(i);
      stopwatch.Stop();
      Console.WriteLine("Elapsed: " + stopwatch.Elapsed.TotalMilliseconds + " ms");

      Console.WriteLine("Testing collectible field multiply:");
      AbstrTest i3 = (AbstrTest)Activator.CreateInstance(
        CreateTypeField("MyClassModule3", true));
      stopwatch = Stopwatch.StartNew();
      accu = 0;
      for (uint i = 0; i < 0xffffffff; i++)
        accu += i3.MyMethod(i);
      stopwatch.Stop();
      Console.WriteLine("Elapsed: " + stopwatch.Elapsed.TotalMilliseconds + " ms");
    }
    catch (Exception e) {
      Console.WriteLine("Exception Caught " + e.Message);
    }
  }
}
使用系统;
运用系统反思;
使用System.Reflection.Emit;
使用系统诊断;
公共抽象类AbstrTest{
公开摘要ulong MyMethod(ulong x);
}
公共类派生类生成器{
私有静态类型CreateTypeConst(字符串名,bool collect){
//创建一个程序集。
AssemblyName myAssemblyName=新的AssemblyName();
myAssemblyName.Name=名称;
AssemblyBuilder myAssembly=AppDomain.CurrentDomain.DefinedDynamicAssembly(
myAssemblyName,collect?AssemblyBuilderAccess.Run和collect:AssemblyBuilderAccess.Run);
//在动态部件中创建动态模块。
ModuleBuilder myModuleBuilder=myAssembly.DefinedDynamicModule(名称);
//在程序集中定义一个名为“MyClass”的公共类。
TypeBuilder myTypeBuilder=myModuleBuilder.DefineType(“MyClass”,TypeAttributes.Public,typeof(AbstrTest));
//创建MyMethod方法。
MethodBuilder myMethodBuilder=myTypeBuilder.DefineMethod(“MyMethod”,
MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.hidebysing,
typeof(ulong),新类型[]{typeof(ulong)};
ILGenerator methodIL=myMethodBuilder.GetILGenerator();
发射方法(操作码Ldarg_1);
发射方法(操作码Ldc_I4_2);
方法发射(操作码转换U8);
发射方法(操作码Mul);
发射方法(操作码Ret);
返回myTypeBuilder.CreateType();
}
私有静态类型CreateTypeField(字符串名称,bool collect){
//创建一个程序集。
AssemblyName myAssemblyName=新的AssemblyName();
myAssemblyName.Name=名称;
AssemblyBuilder myAssembly=AppDomain.CurrentDomain.DefinedDynamicAssembly(
myAssemblyName,collect?AssemblyBuilderAccess.Run和collect:AssemblyBuilderAccess.Run);
//在动态部件中创建动态模块。
ModuleBuilder myModuleBuilder=myAssembly.DefinedDynamicModule(名称);
//在程序集中定义一个名为“MyClass”的公共类。
TypeBuilder myTypeBuilder=myModuleBuilder.DefineType(“MyClass”,TypeAttributes.Public,typeof(AbstrTest));
//在类型中定义名为“MyField”的私有字符串字段。
FieldBuilder myFieldBuilder=myTypeBuilder.DefineField(“MyField”,
typeof(ulong),FieldAttributes.Private | FieldAttributes.Static);
//创建构造函数。
ConstructorBuilder constructor=myTypeBuilder.DefineConstructor(
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig,
调用约定。标准,类型。空类型);
ConstructorInfo superConstructor=typeof(AbstrTest).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
null,Type.EmptyTypes,null);
ILGenerator constructorIL=constructor.GetILGenerator();
构造函数发出(操作码Ldarg_0);
constructorIL.Emit(操作码.Call,超级构造函数);
构造发射(操作码Ldc_I4_2);
构造发射(操作码转换U8);
constructorIL.Emit(操作码.Stsfld,myFieldBuilder);
构造释放(操作码释放);
//创建MyMethod方法。
MethodBuilder myMethodBuilder=myTypeBuilder.DefineMethod(“MyMethod”,
MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.hidebysing,
typeof(ulong),新类型[]{typeof(ulong)};
ILGenerator methodIL=myMethodBuilder.GetILGenerator();
发射方法(操作码Ldarg_1);
methodIL.Emit(opcode.Ldsfld,myFieldBuilder);
发射方法(操作码Mul);
发射方法(操作码Ret);
返回myTypeBuilder.CreateType();
}
公共静态void Main(){
乌龙accu;
秒表;
试一试{
控制台.WriteLine(“测试不可收集常数乘法:”);
AbstrTest i0=(AbstrTest)Activator.CreateInstance(
CreateTypeConst(“MyClassModule0”,false));
stopwatch=stopwatch.StartNew();
accu=0;
对于(uint i=0;i<0xffffffff;i++)
accu+=i0.MyMethod(i);
秒表;
Console.WriteLine(“运行时间:+stopwatch.appeased.totalmillizes+“ms”);
控制台.WriteLine(“测试可收集常数乘:”);
AbstrTest i1=(AbstrTest)Activator.CreateInstance(
CreateTypeConst(“MyClassModule1”,true));
stopwatch=stopwatch.StartNew();
accu=0;
对于(uint i=0;i<0xffffffff;i++)
accu+=i1.MyMethod(i);
秒表;
Console.WriteLine(“运行时间:+stopwatch.appeased.totalmillizes+“ms”);
Console.WriteLine(“测试不可收集字段乘法:”);
AbstrTest i2=(AbstrTest)Activator.CreateInstance(
CreateTypeField(“MyClassModule2”,false));
stopwatch=stopwatch.StartNew();
accu=0;
对于(uint i=0;i<0xffffffff;i++)
accu+=i2.MyMethod(i);
秒表;
骗局
059F0480  push        dword ptr [ebp+0Ch]        ; Ldarg_1, high 32-bits
059F0483  push        dword ptr [ebp+8]          ; Ldarg_1, low 32-bits
059F0486  mov         ecx,59FC8A0h               ; arg2 = DynamicClassDomainId
059F048B  xor         edx,edx                    ; arg1 = DomainId
059F048D  call        JIT_GetSharedNonGCStaticBaseDynamicClass (73E0A6C7h)  
059F0492  push        dword ptr [eax+8]          ; @myFieldBuilder, high 32-bits
059F0495  push        dword ptr [eax+4]          ; @myFieldBuilder, low 32-bits
059F0498  call        @JIT_LMul@16 (73AE1C20h)   ; 64-bit multiply