【问题标题】:64bit method call slow C#64位方法调用慢C#
【发布时间】:2011-11-01 18:17:58
【问题描述】:

嗨,我有一个 32 位应用程序正在移植到 64 位 不知何故,64 位的方法调用比 32 位慢很多。

代码示例

    class huge_class
{
 class subclass0{}
 class subclass1{}
 class subclass2{}
 class subclass3{}
 class subclass4{}
 class subclass5{}
 class subclass6{}
 class subclass7{}
 //so on... say 300

 private object[] GetClassObj(Stopwatch x)
 {
       Console.WriteLine(x.ElapsedMilliseconds.ToString()); //<- the latency can be observed here, the time it takes to execute this line takes a big amount of time
       object[] retObj = new object[300];
       retObj[0] = new subclass0();
       retObj[1] = new subclass1();
       retObj[2] = new subclass2();
       retObj[3] = new subclass3();
       retObj[4] = new subclass4();
       retObj[5] = new subclass5();
       retObj[6] = new subclass6();
            //so on... to 299
 }
}

    Class CallingClass{
  static void Main(string[] args)
    {


        Console.WriteLine("Ready");
        Console.ReadKey();
        huge_class bigClass = new huge_class();
        Console.WriteLine("Init Done");
        Console.ReadKey();
        Stopwatch tmr = Stopwatch.StartNew();
        object[] WholeLottaObj = bigClass.GetClassObj(tmr);
        Console.WriteLine(tmr.ElapsedMilliseconds.ToString());
        Console.WriteLine("Done");
        Console.ReadKey();
}

由于某些奇怪的原因,在 32 位上输入 GetClassObj 比在 64 位版本上更快 我做错了什么

【问题讨论】:

  • 显示调用GetClassObj的代码
  • 为什么你有 300 个子类。你能举一个更实际的例子吗,它实际上慢了多少?
  • @michael,不太清楚:您是在 64 位下编译代码并运行还是只运行 32 位的二进制 compilef?
  • 这个设计闻起来一点也不对,但至少可以缓解你的痛苦:object[] retObj = Enumerable.Range(0, 300).Select(n =&gt; Activator.CreateInstance("MyAssembly", "MyClass.subclass" + n)).ToArray();。 -- 如果类不使用重叠引用,这甚至可以使用 PLinq 自动并行化。
  • 您要解决什么现实问题?即使在 64 位上实例化 300 个类需要 3 倍的时间,但如果你只做一次也没什么大不了的。

标签: c# arrays performance optimization 64-bit


【解决方案1】:

这可能是由于缓存一致性。不要忘记每个引用在 64 位机器上的大小是 32 位机器上的两倍。这意味着:

  • 您的每个实例对象都将变得更大,因此它们将在内存中分布得更远(在 x64 中每个对象的开销更多,并且任何引用字段的大小都会增加一倍)
  • 数组本身大约是原来的两倍

现在很可能,在 32 位 CLR 中,您只是在 CPU 上最快的缓存之一中 - 而在 64 位 CLR 中,您已经超出了它,因此它必须交换内存和交换内存缓存,或者到另一个缓存或主内存。

这就是为什么 x86 是 VS2010(可能是 2008 年;不确定)中可执行项目的默认设置。 This blog post 有更多细节。

【讨论】:

  • 感谢您的及时回复。所以我该怎么做才能让它加载得更快一点。你这似乎很奇怪,因为与 32 位相比,性能冲击是如此之高
  • @michael:到底有多高?你没有显示任何数字。你知道问题是由于构造函数调用还是将值存储在数组中?在这里进行一些调查真的会有所帮助......
  • x86 位版本条目在 5096 毫秒内完成,而 64 位版本在 76000+ 左右进入函数,我将秒表传递给函数以确定调用函数的确切时间。数字来自一个 40000 大小的数组
  • @michael:这只是创建数组一次吗?第二次是不是更快了? (也许您为类型初始化支付了更多费用。)您有多少实际不同的类? “在 76000 左右进入函数”是什么意思?听起来您正在记录一些操作您发布的代码执行了多长时间......您实际计时的时间是多少?
  • @michael:是的 - 所以您向我们展示的代码完全无关紧要 - 这是在您到达 GetClassObj 之前执行的代码,这很重要。不幸的是,我们不知道这是在做什么......
【解决方案2】:

为什么它首先应该更快? 64 位指针操作的重量是内存的两倍(就内存而言),因此 64 位应用程序自然会变慢。

【讨论】:

    猜你喜欢
    • 2021-03-06
    • 2011-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多