0

在我的一些测试中,我需要生成一些程序集,然后使用 ICSharpCode.Decompiler “反编译”它们, ICSharpCode.Decompiler 使用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() ?

4

1 回答 1

2

出于性能原因,我想在内存中生成程序集以避免磁盘 I/O。

这是编程的伟大神话之一。现代操作系统太聪明了,不会让磁盘 I/O 成为瓶颈。您的程序实际上并未将程序集写入磁盘,而是将其写入文件系统缓存。内存。写入磁盘发生在稍后,很久以后,在后台运行并且对性能没有影响的内核线程中。

非常类似地,将“内存”视为 RAM 也是一个神话。程序分配虚拟内存。它根本不是内存,它是在页面文件中分配的空间。在磁盘上。操作系统的工作是在程序需要时为程序提供可用空间。将页面文件分配映射到 RAM。当另一个进程需要 RAM 时,在内核线程中运行的内核线程稍后会写入磁盘。

看到相似之处了吗? 没有区别。您可以观察到的唯一可能的副作用是当您在 RAM 数量非常有限的机器上运行时。当文件系统缓存中没有足够的可用空间时,程序必须等到数据写入文件。这样的机器也很难使 RAM 可用于您的程序。它需要丢弃其他进程(或您自己的)使用的 RAM 页,将它们写入磁盘。换句话说,你的程序启动起来会很慢,而不是完成工作会很慢。净差值接近于零。

程序集的大小永远不会对现代机器上文件系统缓存可用的 RAM 量造成压力。至少一个简单的千兆字节。所以不要打扰,你永远不会真正看到性能改进。

于 2013-11-28T14:28:12.233 回答