【问题标题】:.NET Cross-Assembly Performance Hit.NET 跨程序集性能下降
【发布时间】:2010-11-23 22:23:24
【问题描述】:
我正在阅读 Bill Wagner 的书Effective C#。在第 32 项中,他提倡开发人员创建更小、更有凝聚力的组件,这些组件可以更容易地重用。然而,在同一个项目中,他说:
...额外的安全检查也是
跨装配边界完成。全部
来自同一个程序集的代码
相同的信任级别相同(不是
必须具有相同的访问权限,
但相同的真实水平)。这
CLR 执行一些安全检查
每当代码流穿过程序集时
边界。你的次数越少
程序流跨越汇编
边界,效率越高
是......这些表现都没有
担忧应该会阻止你
分解太
大。性能惩罚是
次要的。
我的问题是每次调用 Foo.dll 的方法都会执行额外的安全检查,还是仅在第一次加载程序集时执行?
谢谢
【问题讨论】:
标签:
c#
.net
performance
assemblies
【解决方案1】:
我还阅读了 Bill Wagner 书中的一段话,对性能也有同样的疑问,所以我对我们目前正在开发的应用程序进行了基准测试:
我们的一个 C# 类有几十万到 3-4 百万次调用。
这个类是在同一个程序集中还是在另一个程序集中,只要它们在同一进程和域中的同一台机器上,它们没有区别。我无法衡量任何显着的性能损失!
当然,如果需要编组调用,情况就不同了。也许非常不同......
【解决方案2】:
.NET 中的安全系统相当复杂。我不确定答案是否像乍一看那样简单。即使您只有一个程序集,仍会执行安全检查。当您启动在单个 .exe 中包含所有逻辑的应用程序时,您不会绕过程序集加载和验证的 .NET 安全检查,也不会绕过类型继承检查。但是,一旦对给定范围的安全性进行了验证,它通常不会再次发生(可能存在一些会强制重新验证证据的缓解情况。)
多个程序集的行为不会有任何不同。可能会有一些额外的程序集加载成本和初始类型访问成本,因为每个新程序集都需要这些初始安全检查。但是,与 JIT 代码本身的过程相比,这些检查通常会相形见绌。
除了基本的程序集加载和类型安全检查之外,您可能还有明确的权限要求。 Microsoft 的系统命名空间充满了 Demand 和 LinkDemand 安全检查,可验证堆栈上的所有调用者(需求)或直接调用者(链接需求)是否有权进行调用。 (您的代码还应包括此类检查,以验证调用者也具有适当的权限。)无论代码位于何处……本地、另一个程序集甚至另一个应用程序域中的程序集中,都将进行这些安全检查.但是,一旦您开始调用其他应用程序域或进程,甚至是服务和其他服务器,编组这些调用和建立连接的开销就会高出几个数量级。
这甚至不是 .NET 安全性的全部内容。一些安全检查比其他安全检查更昂贵。有些需要证书,有些需要证据,等等。安全性不是你可以推卸的……它是现代软件开发的重要组成部分。我不会太担心安全成本……因为它在 .NET 框架和 CLR 中得到了很好的实现和优化。我会尽力确保您的应用程序得到适当的架构和组织。如果将代码分成多个程序集是合乎逻辑的,可以减少维护、部署和重构工作,那么它的 WELL 值得为安全性付出的小额额外成本。
【解决方案3】:
这些安全检查在 CLR 加载程序集时完成。加载程序集后,不需要进一步的安全检查。