none
动态调用的dll 性能会有损失吗? RRS feed

  • 问题

  • 动态调用另一个 c# 写的dll 文件

    调用之后 运行被调用的这个dll 中的程序 会有什么性能损失吗?

    2010年6月29日 11:38

答案

  • 我从以下几个方面来解释可能存在的性能损耗。这个问题比较高级一些,您需要一些 CLR 的知识以便理解这些性能损耗的根源所在。

    但总体上,可以忽略这些损耗,不过,如果您重点考虑性能的话,这些问题不容忽视。

    1、静态引用的程序集会在编译时,由语言编辑器生成程序集引用元数据 (AssemblyRef, FileRef metadata),在程序中用到的任何来自于引用程序集的类型,语言编译器会生成 TypeRef 元数据。CLR 可以方便的从这些元数据中获取需要使用的类型信息。然而,动态引用的程序集 (先不考虑它是否被 NGen) 信息没有被内联到引用它的程序集中,因此,CLR 会花一些时间去加载并确定这些类型,这是一部份较大的性能损耗。

    2、静态引用的程序集可能被强签名,CLR 在加载它时,不需要对整个程序集进行检索以生成一个哈希值,因为被强签名的程序集将此 Hash 值存放到 PE 文件头中的特定区域,CLR 在加载它时,绕过生成 Hash 值的步骤。但动态加载的程序集如果在反射时并没有指定强签名,CLR 会花更多的时间去寻找、确定并加载它。

    3、静态引用的程序集可能被 NGen,这样,JIT 编译器不需要在运行时针对其 IL 代码进行 JIT 到本地代码,这部分时间可以大大被节省。动态加载的程序集如果没有被 NGen,JIT 就会起作用,去编译每一个即将用到的类型和方法到本地代码,从而消耗更多的时间。动态引用被 NGen 的程序集会导致更多的性能问题和不可预料的程序行为,关于这一点,请参考 CLR via C#,第二版,CLR 如何工作这一章。

    希望这些解释对您有帮助。


    Mark Zhou
    2010年6月30日 9:42

全部回复

  • 会有一定的损失,但是很小,不会有大的影响
    .net/asp.net开发群118343907
    2010年6月29日 12:43
  • 如果是通过反射来调用的话,确实会有性能损失,不过只是在反射查找的时候。得到了对象的引用后,再调用方法就和普通的程序集性能一样了。
    Tech Blog: http://gildor.cnblogs.com
    2010年6月29日 12:54
  • 非常感谢,请问 损失主要在那些方法上 我好避免这些
    2010年6月29日 16:01
  • 我从以下几个方面来解释可能存在的性能损耗。这个问题比较高级一些,您需要一些 CLR 的知识以便理解这些性能损耗的根源所在。

    但总体上,可以忽略这些损耗,不过,如果您重点考虑性能的话,这些问题不容忽视。

    1、静态引用的程序集会在编译时,由语言编辑器生成程序集引用元数据 (AssemblyRef, FileRef metadata),在程序中用到的任何来自于引用程序集的类型,语言编译器会生成 TypeRef 元数据。CLR 可以方便的从这些元数据中获取需要使用的类型信息。然而,动态引用的程序集 (先不考虑它是否被 NGen) 信息没有被内联到引用它的程序集中,因此,CLR 会花一些时间去加载并确定这些类型,这是一部份较大的性能损耗。

    2、静态引用的程序集可能被强签名,CLR 在加载它时,不需要对整个程序集进行检索以生成一个哈希值,因为被强签名的程序集将此 Hash 值存放到 PE 文件头中的特定区域,CLR 在加载它时,绕过生成 Hash 值的步骤。但动态加载的程序集如果在反射时并没有指定强签名,CLR 会花更多的时间去寻找、确定并加载它。

    3、静态引用的程序集可能被 NGen,这样,JIT 编译器不需要在运行时针对其 IL 代码进行 JIT 到本地代码,这部分时间可以大大被节省。动态加载的程序集如果没有被 NGen,JIT 就会起作用,去编译每一个即将用到的类型和方法到本地代码,从而消耗更多的时间。动态引用被 NGen 的程序集会导致更多的性能问题和不可预料的程序行为,关于这一点,请参考 CLR via C#,第二版,CLR 如何工作这一章。

    希望这些解释对您有帮助。


    Mark Zhou
    2010年6月30日 9:42
  • namespace Test
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private System.Reflection.Assembly ass;
            private void Form1_Load(object sender, EventArgs e)
            {
                ass = System.Reflection.Assembly.LoadFile(System.IO.Path.Combine(Application.StartupPath, "AxInterop.WMPLib.dll"));
            }
        }
    }

    说明:如果要提高性能,可以把Assembly缓存下来,避免重复LoadFile。这与连接池的思想一样。

    2010年6月30日 10:15
  • 非常感谢各位
    2010年6月30日 11:59