【问题标题】:Assembly.Load performance impactAssembly.Load 性能影响
【发布时间】:2012-09-04 10:21:37
【问题描述】:

我正在开发一个组件,该组件执行使用 ioc 注册的任何接口的临时方法,执行时间取决于不同的触发器。它必须能够将要执行的操作保存到数据库中,因此我将方法名称、类型和参数列表(序列化为 BLOB)保存到数据库中,直到需要为止。

当触发发生时,我需要在一个类型的实例上执行方法。当我使用依赖注入时,我将接口名称保存到数据库中(格式为"Namespace.IInterface, AssemblyName"

要在 ioc 容器上运行 Resolve<IInterface>() 方法,我需要其 Type 的实例:

Assembly assembly = System.Reflection.Assembly.Load(assemblyName);
Type service = assembly.GetType(typeName);
object instance = IOCContainer.Resolve(service);

我的问题是:

  • 有没有更好的方法从 Type 的名称中获取实例,如果 我确定包含程序集已加载到应用程序域中? (我尝试了简单的 Type.Load(typeName) 但得到了 null)
  • 如果相关程序集已加载,CLR 会优化该过程(使用已加载),还是我需要手动缓存程序集列表以防止反复加载相同程序集对性能的影响?

【问题讨论】:

    标签: c# performance clr .net-assembly system.reflection


    【解决方案1】:
    • 如果您使用的typeName 包含程序集名称(类似于MyNamespace.MyType, MyAssembly version=1.0.0.0,publicKeyToken=12345etc),那么Type.Load(typeName) 将获得您的类型,但不会为空;
    • CLR 只负责加载程序集一次(每个上下文一次,details is here,在您的情况下,上下文保持不变,所以答案是您应该放松并将缓存留给 CLR :))。李>

    【讨论】:

    【解决方案2】:

    如果我确定包含的程序集已加载到应用程序域中,是否有更好的方法从其名称中获取类型的实例? (我尝试了简单的 Type.Load(typeName) 但得到了 null)

    没有。

    如果相关程序集已加载,CLR 是否会优化该过程(使用已加载)

    是的。

    每个程序集只加载一次。

    【讨论】:

      【解决方案3】:

      如果相关程序集已加载,CLR 是否会对其进行优化 进程(使用已加载)

      这个问题的答案在 MSDN 文章 How the Runtime Locates Assembliesstep 2 上:

      如果请求的程序集在以前的调用中被请求,公共语言运行时使用的程序集已加载。在命名构成应用程序的程序集时,这可能会产生影响。有关命名程序集的更多信息,请参阅Assembly Names


      与问题没有直接关系,但也很有用:

      如果对程序集的先前请求失败,则对程序集的后续请求将立即失败,而不会尝试加载程序集。从 .NET Framework 2.0 版开始,程序集绑定失败被缓存,缓存的信息用于确定是否尝试加载程序集。

      【讨论】:

        【解决方案4】:

        为了验证性能影响,我尝试加载相同的程序集 n 次。并发现总分配的内存随着每次调用而增长。

        尝试执行以下操作:

        while (true)
        {
            Assembly assembly = Assembly.LoadFrom("abc.dll");
            //monitor: AppDomain.CurrentDomain.MonitoringTotalAllocatedMemorySize
            //memory growing with each call
        }
        

        =============

        然后我这样做是为了确保我只加载一次程序集。

        var typeName = "Namespace.ClassName, Namespace";
        
        while (true)
        {
           var typeFound = Type.GetType(typeName);
           if (typeName == null)
           {
               Assembly assembly = Assembly.LoadFrom("abc.dll");
           }
           //monitor: AppDomain.CurrentDomain.MonitoringTotalAllocatedMemorySize
           //memory will not grow after first call
        }
        

        【讨论】:

          猜你喜欢
          • 2016-05-17
          • 2015-04-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-30
          • 2021-03-09
          相关资源
          最近更新 更多