Cri*_*scu 2 .net performance assemblies .net-assembly
我正在研究的项目将为大量类生成代码 - 预计会有数百到数千个.在生成时不知道实际上将访问多少这些类.
生成的类可以(1)全部存在于单个程序集中(或者可能是少数几个程序集),这些程序集将在脚趾消耗进程启动时加载.
...或者(2)我可以为每个类生成一个程序集,就像Java将每个类编译为单个*.class二进制文件一样,然后提出一种按需加载程序集的机制.
问题是:哪种情况会产生更好的(记忆和时间)表现?
我的直觉是,对于情况(1),加载时间和使用的存储器与构成单个整体组件的类的数量成正比.OTOH,案例(2)带有其复杂性.
如果您知道有关加载程序集内部的任何资源,特别是调用的代码(如果有的话!?)和分配的内存(新加载的程序集的簿记),请分享它们.
您正在试图解决一个不存在的问题,装配装载非常巨资.NET优化.
将大型组件拆分成许多较小的组件毫无疑问是您可以做的最糟糕的事情.到目前为止,加载程序集的最大费用是找到文件.这是一个冷启动问题,CLR加载程序被慢速磁盘阻塞,需要检索和搜索目录条目以找到包含文件内容的磁盘扇区.当可以从文件系统缓存中检索程序集数据时,此问题在热启动时消失.请注意,Java也不是这样做的,它将.class文件打包成.jar..jar是装配的粗略等价物.
找到文件后,.NET使用操作系统工具来实际加载程序集数据非常便宜.它使用内存映射文件.这仅涉及为文件保留虚拟内存而不是从文件中读取.
读取直到稍后才会发生,并且由页面错误完成.任何需求分页虚拟内存操作系统的功能.访问虚拟内存会产生页面错误,操作系统会从文件中加载数据并将虚拟内存页面映射到RAM中.程序继续之后,永远不会意识到它被操作系统中断了.它将是产生这些页面错误的抖动,它访问程序集中的元数据表以找到方法的IL.然后从中生成可执行的机器代码.
此方案的一个自动好处是,您永远不会支付程序集中但未使用的代码.抖动根本没有理由查看包含IL的文件部分,因此它实际上从未被读取过.
并注意到这种方案的缺点,第一次使用类确实涉及由于磁盘读取而导致的性能损失.这需要以这种或那种方式支付,在.NET中,债务应该在最后一刻到期.这就是为什么属性因速度慢而闻名的原因.
较大的组件总是比许多较小的组件更好.