程序集中的类数如何影响性能?

时间:2012-11-16 14:00:44

标签: .net performance assemblies .net-assembly

我正在研究的项目将为大量类生成代码 - 预计会有数百到数千个。 在生成时不知道实际上将访问多少这些类。

生成的类可以(1)全部存在于单个程序集中(或者可能是少数程序集),这些程序将在脚趾消耗过程开始时加载。

...或(2)我可以为每个类生成一个程序集,就像Java将每个类编译为单个*.class二进制文件一样,然后想出一个按需加载程序集的机制。

问题:哪种情况会产生更好的(记忆和时间)表现?

我的直觉是,对于情况(1),加载时间和使用的存储器与构成单个整体组件的类的数量成正比。 OTOH,案例(2)带来了复杂性。

如果您知道任何与加载程序集内部相关的资源,特别是调用的代码(如果有的话!?)和分配的内存(新加载的程序集的簿记),请分享它们。

2 个答案:

答案 0 :(得分:9)

您正在尝试解决不存在的问题,在.NET中对装配加载非常进行了大量优化。

将大型装配拆分成许多较小的装配毫无疑问是你能做的最糟糕的事情。到目前为止,加载程序集的最大费用是找到文件。这是冷启动问题,CLR加载程序被慢速磁盘阻塞,需要检索和搜索目录条目以找到包含文件内容的磁盘扇区。当可以从文件系统缓存中检索程序集数据时,此问题在热启动上消失。请注意,Java也不是这样做的,它将.class文件打包成.jar。 .jar是大会的粗略等价物。

找到文件后,.NET使用操作系统工具来实际加载程序集数据非常便宜。它使用内存映射文件。这仅涉及为文件保留虚拟内存,但从文件中读取。

直到稍后才开始阅读,并且由页面错误完成。任何需求分页虚拟内存操作系统的功能。访问虚拟内存会产生页面错误,操作系统会从文件中加载数据并将虚拟内存页面映射到RAM中。程序继续之后,永远不会意识到它被操作系统中断了。它将是产生这些页面错误的抖动,它访问程序集中的元数据表以找到方法的IL。然后从中生成可执行的机器代码。

此方案的一个自动好处是,您永远不会支付程序集中但未使用的代码。抖动根本没有理由查看包含IL的文件部分,因此它实际上永远不会被读取。

并注意到这种方案的缺点,第一次使用类确实涉及由于磁盘读取而导致的性能损失。这需要以这种或那种方式支付,在.NET中,债务应该在最后一刻到期。这就是为什么属性因为速度慢而闻名。

更大的装配体总是比许多小型装配体更好。

答案 1 :(得分:2)

  

哪种情况会产生更好的(记忆和时间)表现

请记住编译器会为您做很多优化,选项1绝对是可行的方法。在每个类中有一个单独的程序集似乎完全过分。不仅如此,您可能会发现加载1个大型装配比使用大型装配更快。

此外,这确实感觉就像过早优化我的建议将坚持使用第一个(理智)选项,如果您认为有必要,可以将类拆分为单独的程序集。