Imp*_*rks 6 c# compilation roslyn
我正在将一个应用程序从 .NET Framework 移植到 .NET Core,它使用运行时代码生成。
这是旧代码:
var refs = new []
{
typeof(Foo).Assembly.Location,
typeof(Enumerable).Assembly.Location
};
var options = new CompilerParameters(refs)
{
GenerateExecutable = false,
GenerateInMemory = true
};
var provider = new CSharpCodeProvider();
var result = provider.CompileAssemblyFromSource(options, rawText);
return result.CompiledAssembly;
Run Code Online (Sandbox Code Playgroud)
使用 Roslyn 的新代码如下所示:
var root = Path.GetDirectoryName(typeof(object).Assembly.Location);
var typeRefs = new[]
{
typeof(object).Assembly.Location,
Path.Combine(root, "System.Collections.dll"),
Path.Combine(root, "System.Runtime.dll"),
typeof(Foo).Assembly.Location,
typeof(Enumerable).Assembly.Location
};
var source = Measure("SourceText", () => SourceText.From(rawText));
var parseOptions = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7);
var syntaxTree = Measure("Parse", () => SyntaxFactory.ParseSyntaxTree(source, parseOptions));
var compilation = Measure("Compile", () => CSharpCompilation.Create(
"Bar.dll",
new[] {syntaxTree},
typeRefs.Select(x => MetadataReference.CreateFromFile(x)),
new CSharpCompilationOptions(
OutputKind.DynamicallyLinkedLibrary,
optimizationLevel: OptimizationLevel.Debug
)
));
using var stream = new MemoryStream();
var emitResult = Measure("Emit", () => compilation.Emit(stream));
if(!emitResult.Success)
throw new Exception("Failed to compile parser code!");
stream.Seek(0, SeekOrigin.Begin);
return Assembly.Load(stream.ToArray());
Run Code Online (Sandbox Code Playgroud)
问题是:新代码的运行速度至少慢了 2 倍。我使用了一个非常简单的Measure函数来追踪瓶颈:
private static T Measure<T>(string caption, Func<T> generator)
{
var now = DateTime.Now;
var result = generator();
var end = DateTime.Now - now;
Debug.WriteLine($"{caption}: {end.TotalMilliseconds} ms");
return result;
}
Run Code Online (Sandbox Code Playgroud)
这是它打印的内容:
SourceText: 4,7926 ms
Parse: 598,5749 ms
Compile: 43,4261 ms
Emit: 5256,0411 ms
Run Code Online (Sandbox Code Playgroud)
如您所见,生成程序集compilation.Emit需要花费 5.2 秒之多。
有什么办法可以加快这个速度吗?也许选项中的一些标志会影响编译时间?我尝试了以下操作,但没有成功:
OptimizationLevel.Debug在和之间更改OptimizationLevel.Release有任何想法吗?
| 归档时间: |
|
| 查看次数: |
738 次 |
| 最近记录: |