问题描述
我是用罗斯林编译到一个动态组装时具有的性能麻烦。编译正在采取〜3秒,相比〜300毫秒使用的CodeDOM
时,编译器编译相同的代码。下面是我用做汇编代码的一个削减的版本:
VAR编译= CSharpCompilation.Create(
UserPayRules.dll,
syntaxTrees,
assembliesToAdd);使用(VAR流=新的MemoryStream())
{
stopWatch.Start()
;
VAR的结果= compilation.Emit(流);
stopWatch.Stop();
的Debug.WriteLine(编译:{0},stopWatch.ElapsedMilliseconds); (!result.Success)
如果
{
抛出新的InvalidOperationException异常();
}
无功组件=的Assembly.Load(stream.GetBuffer());
}
的建议,为了加快速度传递ModuleBuilder物体插入的Emit方法,而不是一个MemoryStream的。我试图按照这种模式,就像这样:
VAR编译= CSharpCompilation.Create(
UserPayRules.dll ,
syntaxTrees,
assembliesToAdd);
VAR assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
新的AssemblyName(ThisAssembly),
AssemblyBuilderAccess.RunAndCollect);
VAR moduleBuilder = assemblyBuilder.DefineDynamicModule(ThisModule);
VAR的结果= compilation.Emit(moduleBuilder);
的Debug.WriteLine(编译:{0},stopWatch.ElapsedMilliseconds); (!result.Success)
如果
{
抛出新的InvalidOperationException异常();
}
无功组件=的Assembly.Load(stream.GetBuffer());
但我的罗斯林的版本显然不具备散发出过载
方法,它接受 ModuleBuilder
。这版本是:
ID: Microsoft.CodeAnalysis
版本: 0.6。 4033103-β(预发行)
项目信息:
显然,这是一个预发布,所以它不是奇怪的是,API可能已经改变。不过,
我的问题(S)
- 有谁知道为什么
的Emit
办法似乎不再具有过载,需要一个ModuleBuilder
? - 有另一种方式,同时还使用罗斯林(罗斯林在
的CodeDOM
和Mono,我不想放弃编译器提供了一些优势)?使这个编译更快
目前罗丝琳不公开发出动态程序集的能力。我们删除它,因为它是有问题的。
您还可以发射到的MemoryStream
使用 Compilation.Emit
的API,然后使用的Assembly.Load(字节[])
来加载生成的二进制文件。
请注意,此组件将不会被释放,直到含的AppDomain
被卸载。
I was having trouble with performance when using Roslyn to compile to a dynamic assembly. Compilation was taking ~3 seconds, compared to ~300 milliseconds to compile the same code when using the CodeDom
compiler. Here's a pared-down version of the code I'm using to do the compilation:
var compilation = CSharpCompilation.Create(
"UserPayRules.dll",
syntaxTrees,
assembliesToAdd);
using (var stream = new MemoryStream())
{
stopWatch.Start();
var result = compilation.Emit(stream);
stopWatch.Stop();
Debug.WriteLine("Compilation: {0}", stopWatch.ElapsedMilliseconds);
if (!result.Success)
{
throw new InvalidOperationException();
}
var assembly = Assembly.Load(stream.GetBuffer());
}
This answer suggests passing a ModuleBuilder object into the Emit method instead of a MemoryStream in order to speed things up. I tried to follow that pattern, like so:
var compilation = CSharpCompilation.Create(
"UserPayRules.dll",
syntaxTrees,
assembliesToAdd);
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("ThisAssembly"),
AssemblyBuilderAccess.RunAndCollect);
var moduleBuilder = assemblyBuilder.DefineDynamicModule("ThisModule");
var result = compilation.Emit(moduleBuilder);
Debug.WriteLine("Compilation: {0}", stopWatch.ElapsedMilliseconds);
if (!result.Success)
{
throw new InvalidOperationException();
}
var assembly = Assembly.Load(stream.GetBuffer());
But my version of Roslyn apparently doesn't have an overload of the Emit
method that takes a ModuleBuilder
. That version is:
Id: Microsoft.CodeAnalysis
Version: 0.6.4033103-beta (Prerelease)
Project Information: http://msdn.microsoft.com/en-US/roslyn
Obviously, this is a prerelease, so it's not strange that the api might have changed. However,
My Question(s)
- Does anyone know why the
Emit
method no longer seems to have an overload that takes aModuleBuilder
? - Is there another way to make this compilation faster while still using Roslyn (Roslyn offers a couple advantages over the
CodeDom
and Mono compilers that I'd prefer not to give up)?
Roslyn currently doesn't expose ability to emit dynamic assemblies. We removed it because it was problematic.
You can still emit to a MemoryStream
using Compilation.Emit
APIs and then use Assembly.Load(byte[])
to load the resulting binary.
Note that this assembly won't be freed until the containing AppDomain
is unloaded.
这篇关于使用罗斯林的Emit方法用一个ModuleBuilder,而不是一个MemoryStream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!