C# 一个动态程序集中的多个类型要比多个动态程序集中的每个类型慢得多
因此,我通过C# 一个动态程序集中的多个类型要比多个动态程序集中的每个类型慢得多,c#,reflection.emit,C#,Reflection.emit,因此,我通过definedynamicsassembly发出一些动态代理,在测试时我发现: 每个动态程序集有一种类型:快速,但占用大量内存 一个动态程序集中的所有类型:非常慢,但占用的内存要少得多 在我的测试中,我生成了10000个类型,每个程序集代码的一个类型运行速度大约快8-10倍。内存使用量完全符合我的预期,但是为什么生成类型的时间要长那么多呢 编辑:添加了一些示例代码 一个大会: var an = new AssemblyName( "Foo" ); var ab = AppDoma
definedynamicsassembly
发出一些动态代理,在测试时我发现:
- 每个动态程序集有一种类型:快速,但占用大量内存
- 一个动态程序集中的所有类型:非常慢,但占用的内存要少得多
var an = new AssemblyName( "Foo" );
var ab = AppDomain.CurrentDomain.DefineDynamicAssembly( an, AssemblyBuilderAccess.Run );
var mb = ab.DefineDynamicModule( "Bar" );
for( int i = 0; i < 10000; i++ )
{
var tb = mb.DefineType( "Baz" + i.ToString( "000" ) );
var met = tb.DefineMethod( "Qux", MethodAttributes.Public );
met.SetReturnType( typeof( int ) );
var ilg = met.GetILGenerator();
ilg.Emit( OpCodes.Ldc_I4, 4711 );
ilg.Emit( OpCodes.Ret );
tb.CreateType();
}
var-an=newassemblyname(“Foo”);
var ab=AppDomain.CurrentDomain.DefinedDynamicAssembly(an,AssemblyBuilderAccess.Run);
var mb=ab.DefinedDynamicModule(“Bar”);
对于(int i=0;i<10000;i++)
{
var tb=mb.DefineType(“Baz”+i.ToString(“000”);
var met=tb.DefineMethod(“Qux”,MethodAttributes.Public);
met.SetReturnType(typeof(int));
var ilg=met.GetILGenerator();
ilg.Emit(操作码.Ldc_i44711);
ilg.Emit(操作码Ret);
tb.CreateType();
}
每种类型一个组件:
for( int i = 0; i < 10000; i++ )
{
var an = new AssemblyName( "Foo" );
var ab = AppDomain.CurrentDomain.DefineDynamicAssembly( an,
AssemblyBuilderAccess.Run );
var mb = ab.DefineDynamicModule( "Bar" );
var tb = mb.DefineType( "Baz" + i.ToString( "000" ) );
var met = tb.DefineMethod( "Qux", MethodAttributes.Public );
met.SetReturnType( typeof( int ) );
var ilg = met.GetILGenerator();
ilg.Emit( OpCodes.Ldc_I4, 4711 );
ilg.Emit( OpCodes.Ret );
tb.CreateType();
}
for(int i=0;i<10000;i++)
{
var an=新的程序集名称(“Foo”);
var ab=AppDomain.CurrentDomain.DefinedDynamicAssembly(an,
AssemblyBuilderAccess.Run);
var mb=ab.DefinedDynamicModule(“Bar”);
var tb=mb.DefineType(“Baz”+i.ToString(“000”);
var met=tb.DefineMethod(“Qux”,MethodAttributes.Public);
met.SetReturnType(typeof(int));
var ilg=met.GetILGenerator();
ilg.Emit(操作码.Ldc_i44711);
ilg.Emit(操作码Ret);
tb.CreateType();
}
在使用C#7.0的LINQPad中的PC上,我得到一个大约8.8秒的程序集,每种类型一个程序集大约2.6秒。一个程序集中的大部分时间都在DefineType
和CreateType
中,而时间主要在defineddynamicassembly
+defineddynamicmodule
中
DefineType
检查是否存在名称冲突,这是一个字典
查找。如果字典
为空,这是关于检查null
大部分时间都花在CreateType
上,但我不知道在哪里,但是似乎需要额外的时间将类型添加到单个模块中
创建多个模块会降低整个过程的速度,但大部分时间都花在创建模块和
DefineType
中,它必须扫描每个模块以查找重复的模块,因此现在已增加到10000次null
检查。每个类型有一个唯一的模块,CreateType
速度非常快。在我的检查中,关于为什么在一个程序集中定义多个模块比使用一个模块创建新程序集慢,使用以下代码段:
单个组装场景:
var-an=newassemblyname(“Foo”);
var ab=AppDomain.CurrentDomain.DefinedDynamicAssembly(an,AssemblyBuilderAccess.Run);
对于(int i=0;i<10000;i++)
{
ab.定义的动态模块(“Bar”+i.ToString(“000”);
}
多装配场景:
var-an=newassemblyname(“Foo”);
对于(int i=0;i<10000;i++)
{
var ab=AppDomain.CurrentDomain.DefinedDynamicAssembly(an,AssemblyBuilderAccess.Run);
ab.定义的动态模块(“Bar”);
}
DefinedDynamicModule()
处于压力之下。但是,当使用多个程序集时,永远不会调用此方法;相反,其余50%由其他方法负责DefineDynamicModule()
函数。相反,我们找到了CLI的getInMemorySemblyModule()
方法来检索有关清单模块(自动创建的模块)的信息
所以这里我们有一点性能增益;对于一个组件,我们得到10001个模块,但是对于多个组件,我们总共得到10000个模块。虽然不多,但这一个额外的模块不应该是背后的主要原因
II.6.5当项目位于当前组件中,但属于模块的一部分而不是包含清单的模块时,应使用.module extern指令在组件的清单中声明定义模块
第146页
及
II.6.7清单模块(每个程序集只能有一个)包括.assembly指令。要导出在程序集的任何其他模块中定义的类型,需要程序集清单中的条目
第146页
因此,每次创建新模块时,实际上都在添加一个新文件
var an = new AssemblyName("Foo");
var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
for (int i = 0; i < 10000; i++)
{
ab.DefineDynamicModule("Bar" + i.ToString("000"));
}
var an = new AssemblyName("Foo");
for (int i = 0; i < 10000; i++)
{
var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
ab.DefineDynamicModule("Bar");
}