c# – 罗斯林启动时间慢
发布时间:2020-12-15 05:37:12 所属栏目:百科 来源:网络整理
导读:我注意到Roslyn解析/编译的启动时间是一个相当重要的一次性成本.编辑:我正在使用Roslyn CTP MSI(程序集在GAC中).这是预期的吗?有没有解决方法? 运行下面的代码与1次迭代(约3秒)和300次迭代(约3秒)的时间几乎相同. [Test]public void Test(){ var iters =
我注意到Roslyn解析/编译的启动时间是一个相当重要的一次性成本.编辑:我正在使用Roslyn CTP MSI(程序集在GAC中).这是预期的吗?有没有解决方法?
运行下面的代码与1次迭代(约3秒)和300次迭代(约3秒)的时间几乎相同. [Test] public void Test() { var iters = 300; foreach (var i in Enumerable.Range(0,iters)) { // Parse the source file using Roslyn SyntaxTree syntaxTree = SyntaxTree.ParseText(@"public class Foo" + i + @" { public void Exec() { } }"); // Add all the references we need for the compilation var references = new List<MetadataReference>(); references.Add(new MetadataFileReference(typeof(int).Assembly.Location)); var compilationOptions = new CompilationOptions(outputKind: OutputKind.DynamicallyLinkedLibrary); // Note: using a fixed assembly name,which doesn't matter as long as we don't expect cross references of generated assemblies var compilation = Compilation.Create("SomeAssemblyName",compilationOptions,new[] {syntaxTree},references); // Generate the assembly into a memory stream var memStream = new MemoryStream(); // if we comment out from this line and down,the runtime drops to ~.5 seconds EmitResult emitResult = compilation.Emit(memStream); var asm = Assembly.Load(memStream.GetBuffer()); var type = asm.GetTypes().Single(t => t.Name == "Foo" + i); } } 解决方法
我认为一个问题是使用内存流,而应该尝试使用动态模块和ModuleBuilder.总体而言,代码执行速度更快,但仍然有较重的首次加载方案.我自己对罗斯林很陌生,所以我不确定为什么这会更快,但这里是改变的代码.
var iters = 300; foreach (var i in Enumerable.Range(0,iters)) { // Parse the source file using Roslyn SyntaxTree syntaxTree = SyntaxTree.ParseText(@"public class Foo" + i + @" { public void Exec() { } }"); // Add all the references we need for the compilation var references = new List<MetadataReference>(); references.Add(new MetadataFileReference(typeof(int).Assembly.Location)); var compilationOptions = new CompilationOptions(outputKind: OutputKind.DynamicallyLinkedLibrary); // Note: using a fixed assembly name,which doesn't matter as long as we don't expect cross references of generated assemblies var compilation = Compilation.Create("SomeAssemblyName",new[] { syntaxTree },references); var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new System.Reflection.AssemblyName("CustomerA"),System.Reflection.Emit.AssemblyBuilderAccess.RunAndCollect); var moduleBuilder = assemblyBuilder.DefineDynamicModule("MyModule"); System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); // if we comment out from this line and down,the runtime drops to ~.5 seconds var emitResult = compilation.Emit(moduleBuilder); watch.Stop(); System.Diagnostics.Debug.WriteLine(watch.ElapsedMilliseconds); if (emitResult.Diagnostics.LongCount() == 0) { var type = moduleBuilder.GetTypes().Single(t => t.Name == "Foo" + i); System.Diagnostics.Debug.Write(type != null); } } 通过使用这种技术,编译只需96毫秒,在后续迭代中需要大约3到15毫秒.所以我认为你可能在第一个负载场景方面增加一些开销. 对不起,我无法解释为什么它更快!我自己就是在研究Roslyn,今晚晚些时候会做更多的挖掘,看看我是否能找到更多关于ModuleBuilder在内存流上提供的证据. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |