草庐IT

c# - LoaderOptimizationAttribute 的作用

coder 2024-05-27 原文

我已经写了一小段关于动态加载程序集和从这些程序集创建类实例的代码,包括一个可执行文件、一个要动态加载的测试库和一个将动态程序集加载到新 中的加载器库应用域。加载程序库被可执行文件和动态库引用。

//executable
[System.STAThreadAttribute()]
[System.LoaderOptimization(LoaderOptimization.MultiDomain)]
static void Main(string[] args)
{       
    AppDomainSetup domainSetup = new AppDomainSetup()
    {
        ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
        ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,
        ApplicationName = AppDomain.CurrentDomain.SetupInformation.ApplicationName,
        LoaderOptimization = LoaderOptimization.MultiDomain
    };
    AppDomain childDomain = AppDomain.CreateDomain("MyDomain", null, domainSetup);
    Console.WriteLine(AppDomain.CurrentDomain.SetupInformation.LoaderOptimization.ToString());
    Console.WriteLine(childDomain.SetupInformation.LoaderOptimization.ToString());

    byte[] assembly = null;
    string assemblyName = "CSTestLib"; 

    using (FileStream fs = new FileStream(assemblyName+".dll",FileMode.Open))
    {
        byte[] byt = new byte[fs.Length];
        fs.Read(byt,0,(int)fs.Length);
        assembly = byt;          
    }

    object[] pararmeters = {assemblyName,assembly}; 
    string LoaderAssemblyName = typeof(AssemblyLoader).Assembly.FullName;
    string LoaderClassName = typeof(AssemblyLoader).FullName;
    AssemblyLoader assloader = (AssemblyLoader)childDomain.CreateInstanceAndUnwrap(LoaderAssemblyName,LoaderClassName , true, BindingFlags.CreateInstance, null, parameters, null, null);


    object obj = assloader.Load("CSTestLib.Class1");
    object obj2 = assloader.Load("CSTestLib.Class2");

    AppDomain.Unload(childDomain);

    Console.ReadKey();
}

//Dynamic Lib
using System;


namespace CSTestLib
{
    public class Class1 :MarshalByRefObject
    {
        public Class1() { }
    }



    public class Class2 : MarshalByRefObject
    {
        public Class2() { }
    }
}

//Loader Library


using System;

namespace LoaderLibrary
{
    public class AssemblyLoader : MarshalByRefObject
    {
        string assemblyName;
        public AssemblyLoader(string assName, byte[] ass)
        {
            assemblyName = assName;
            AppDomain.CurrentDomain.Load(ass);
            Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + " " + AppDomain.CurrentDomain.SetupInformation.LoaderOptimization.ToString());
        }

        public object Load(string className)
        {
            object ret = null;
            try
            {
                ret = AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName, className);
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return ret;
        }
    }
}
  1. 这里我在 main() 方法上设置了 LoaderOptimizationAttribute 但是 AppDomain.CurrentDomain.SetupInformation.LoaderOptimization.ToString(); 说它是 NotSpecified 为什么?

  2. MultiDomainMultiDomainHost 之间的区别我不是很清楚。 MultiDomainHost 是否仅适用于 GAC 程序集?对于我的情况,哪种更合适?

  3. 根据 this

    JIT-compiled code cannot be shared for assemblies loaded into the load-from context, using the LoadFrom method of the Assembly class, or loaded from images using overloads of the Load method that specify byte arrays.

那么我如何检测程序集是否以域中立的方式加载?我如何确保它加载的是域中立的?

最佳答案

此属性仅在您使用 NGen 预编译程序集时有效加速应用程序的热启动。当您指定 MultiDomainMultiDomainHost 时,您可以使用预编译 (ngenned) 程序集。您可以使用 Process Explorer 验证这一点,您可以在其中查看已加载模块的列表。

如果您的应用程序包含多个共享程序集的可执行实例,这将是最节省启动时间的方法之一。这使 .NET 能够在进程之间共享代码页,从而节省实际内存(一个程序集在物理内存中只存在一次,但它在一个或多个进程之间共享)并防止在每个进程中一遍又一遍地 JITing 相同的代码这需要时间,但代价是生成的代码效率会降低一些,因为它可能会使用常规 JIT 进行编译,而常规 JIT 可以使用更多动态数据来生成最高效的代码。

在您的示例中,您将程序集加载到位于托管堆中的字节数组中,并增加了您的私有(private)字节数。这使得进程之间无法共享数据。只有在你的硬盘上有对应的只读页面才能在进程之间共享。这就是该属性无效的原因。如果您追求 2 倍的热启动性能,这就是您要寻找的属性。对于其他任何事情都无关紧要。

现在回到你原来的问题:

  1. 已设置,但当您在调试器下启动应用程序时,此 MultiDomain 属性将被忽略。当您在调试器之外启动它时,您将获得预期的结果。
  2. MultiDomainHost 确实启用了 AppDomain 中立性,仅为已签名的程序集所有其他不共享。
  3. 代码共享只有在预编译时才会发生。真正的问题是:如何检查程序集是否已预编译?我使用 Process Explorer 查看已加载模块的列表来完成此操作。当我加载的程序集显示出带有本地镜像缓存的路径和 .ni 扩展名时,我确定正在使用预编译图像。当您将单选按钮设置为原生图像时,您也可以使用 fuslogvw 来检查这一点,以检查运行时未使用原生图像的原因。

关于c# - LoaderOptimizationAttribute 的作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5783228/

有关c# - LoaderOptimizationAttribute 的作用的更多相关文章

  1. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  2. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  3. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  4. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  5. ruby-on-rails - "assigns"在 Ruby on Rails 中有什么作用? - 2

    我目前正在尝试学习RubyonRails和测试框架RSpec。assigns在此RSpec测试中做什么?describe"GETindex"doit"assignsallmymodelas@mymodel"domymodel=Factory(:mymodel)get:indexassigns(:mymodels).shouldeq([mymodel])endend 最佳答案 assigns只是检查您在Controller中设置的实例变量的值。这里检查@mymodels。 关于ruby-o

  6. ruby - 字符串文字前面的 * 在 ruby​​ 中有什么作用? - 2

    这段代码似乎创建了一个范围从a到z的数组,但我不明白*的作用。有人可以解释一下吗?[*"a".."z"] 最佳答案 它叫做splatoperator.SplattinganLvalueAmaximumofonelvaluemaybesplattedinwhichcaseitisassignedanArrayconsistingoftheremainingrvaluesthatlackcorrespondinglvalues.Iftherightmostlvalueissplattedthenitconsumesallrvaluesw

  7. ruby - 为什么这个 eval 在 Ruby 中不起作用 - 2

    你能解释一下吗?我想评估来自两个不同来源的值和计算。一个消息来源为我提供了以下信息(以编程方式):'a=2'第二个来源给了我这个表达式来评估:'a+3'这个有效:a=2eval'a+3'这也有效:eval'a=2;a+3'但我真正需要的是这个,但它不起作用:eval'a=2'eval'a+3'我想了解其中的区别,以及如何使最后一个选项起作用。感谢您的帮助。 最佳答案 您可以创建一个Binding,并将相同的绑定(bind)与每个eval相关联调用:1.9.3p194:008>b=binding=>#1.9.3p194:009>eva

  8. ruby-on-rails - Spring 不起作用。 [未初始化常量 Spring::SID::DL] - 2

    我无法运行Spring。这是错误日志。myid-no-MacBook-Pro:myid$spring/Users/myid/.rbenv/versions/1.9.3-p484/lib/ruby/gems/1.9.1/gems/spring-0.0.10/lib/spring/sid.rb:17:in`fiddle_func':uninitializedconstantSpring::SID::DL(NameError)from/Users/myid/.rbenv/versions/1.9.3-p484/lib/ruby/gems/1.9.1/gems/spring-0.0.10/li

  9. c# - C# 中的 Flatten Ruby 方法 - 2

    我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume

  10. ruby - 可以像在 C# 中使用#region 一样在 Ruby 中使用 begin/end 吗? - 2

    我最近从C#转向了Ruby,我发现自己无法制作可折叠的标记代码区域。我只是想到做这种事情应该没问题:classExamplebegin#agroupofmethodsdefmethod1..enddefmethod2..endenddefmethod3..endend...但是这样做真的可以吗?method1和method2最终与method3是同一种东西吗?还是有一些我还没有见过的用于执行此操作的Ruby惯用语? 最佳答案 正如其他人所说,这不会改变方法定义。但是,如果要标记方法组,为什么不使用Ruby语义来标记它们呢?您可以使用

随机推荐