在我的一些测试中,我需要生成一些程序集,然后使用ICSharpCode.Dompiler对它们进行"反编译",该编译器使用Mono.Cecil来检查程序集。
出于性能原因,我希望在内存中生成程序集,以避免磁盘I/O。
贝娄,你可以找到一些我打算使用的代码:
var cdp = CodeDomProvider.CreateProvider(CodeDomProvider.GetLanguageFromExtension("cs"));
var p = new CompilerParameters { GenerateInMemory = true } ;
var cr = cdp.CompileAssemblyFromSource(p, sources);
if (cr.Errors.Count > 0)
{
throw new Exception(cr.Errors[0].ErrorText);
}
// !!! I'd like to avoid building / loading the assembly to / from disk
// var assembly = AssemblyDefinition.ReadAssembly(assemblyPath, readerParameters);
// Instead, I'd like to do something like:
Stream assemblyStream = GetAssemblyContentAsStream(cr.CompiledAssembly);
var assembly = AssemblyDefinition.ReadAssembly(assemblyStream, readerParameters);
var dc = new DecompilerContext(assembly.MainModule);
var astBuilder = new AstBuilder(dc);
astBuilder.AddType(typeToBeConverted);
var output = new StringWriter();
astBuilder.GenerateCode(new PlainTextOutput(output));
所以问题是:是否可以实现GetAssemblyContentAsStream()?
出于性能原因,我希望在内存中生成程序集,以避免磁盘I/O。
这是编程的一大神话。现代操作系统过于智能,无法使磁盘I/O成为瓶颈。您的程序实际上并没有将程序集写入磁盘,而是将其写入文件系统缓存。内存在后台运行并且对性能没有影响的内核线程中,写入磁盘的操作要晚得多
同样,将"内存"视为RAM也是一个神话。程序分配虚拟内存。它根本不是内存,而是在分页文件中分配的空间。在磁盘上。操作系统的工作是在程序需要时为其提供可用空间。将分页文件分配映射到RAM。写入磁盘的操作发生在内核线程中,该线程在另一个进程需要RAM时运行。
看到相似之处了吗没有区别。你能观察到的唯一可能的副作用是当你在RAM非常有限的机器上运行时。当文件系统缓存中没有足够的可用空间时,程序必须等待,直到数据写入文件。这样的机器也会有很大的困难,使RAM可用于您的程序。它需要抛出其他进程(或您自己的进程)使用的RAM页面,将它们写入磁盘。换句话说,你的程序开始时会很慢,而不是完成工作时很慢。净差额接近于零。
程序集的大小永远不会给现代机器上文件系统缓存的可用RAM量带来压力。一个简单的最小GB。所以,别担心,你永远不会真正看到性能的提高。