C#大型阵列的内存优化

v00*_*d00 4 c# c++ optimization performance

以下是c ++和c#中的两个代码部分,完全相同:

C++
http://ideone.com/UfL5R

#include <stdio.h>
int main(int argc, char *argv[]) {
  char p[1000000];
  unsigned int i,j;
  unsigned long long s=0;
  for(i=2;i<1000000;i++) p[i]=1;
  for(i=2;i<500000;) {
    for(j=2*i;j<1000000;j+=i) p[j]=0;
    for(i++;!p[i];i++);
  }
  for(i=3,s=2;i<1000000;i+=2) if(p[i]) s+=i;
  printf ("%lld\n",s);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

时间:0.01s memmory:2576 kB

C#
http://ideone.com/baXYm

using System;

namespace ConsoleApplication4
{
    internal class Program
    {
        private  static void Main(string[] args)
        {
            var p = new byte[1000000];
            ulong i, j;
            double s = 0;
            for(i=2;i<1000000;i++) 
                p[i]=1;

            for(i=2;i<500000;) 
            {
                for(j=2*i;j<1000000;j+=i) 
                    p[j]=0;
                for(i++;p[i]==0;i++);
            }

            for(i=3,s=2;i<1000000;i+=2) 
                if(p[i]!=0) s+=i;

            Console.WriteLine(s);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

时间:0.05s mem:38288 kB

如何改进C#代码以证明C#可以和我的同事一样快C++?

正如您所看到的,C#执行时间大5倍,内存消耗大15倍.

Dar*_*rov 9

编译并在发布模式下运行.在构建并在发布模式下运行时,我从C#版本获得0.01s.就内存消耗而言,您正在将苹果与橙子进行比较.托管环境将占用更多内存,因为它托管CLR和垃圾收集器,而这些内存并非免费.


jal*_*alf 6

如何改进C#代码以证明C#可以和我的同事一样快C++?

你不能.有一些合法的领域,C++从根本上比C#更快.但也有一些领域,C#代码将比同等的C++代码表现更好.他们是不同的语言,有不同的优点和缺点.

但作为程序员,你真的应该把你的决定建立在逻辑上.

逻辑规定您应首先收集信息,然后根据该信息做出决定.

相反,您首先做出决定,然后寻找支持它的信息.如果你是一名政治家,那可能会奏效,但这不是编写软件的好方法.

不要去寻找C#比C++更快的证据.相反,在您的情况下检查哪个选项更快.

在任何情况下,如果你想证明X可以像Y一样快,你必须按照通常的方式去做:使X和Y一样快.而且一如既往,在进行性能调整时,分析器是你最好的朋友.找出确切花费额外时间的地方,然后弄清楚如何消除它.

但内存使用是一个失败的原因..NET只使用更多内存,原因如下:

  • 它有一个更大的运行时库,它必须存在于进程的地址空间中
  • .NET对象具有C++类中不存在的其他成员,因此它们使用更多内存
  • 垃圾收集器意味着你通常会有一些"不再使用但尚未回收"的内存.在C++中,通常会立即释放内存.在.NET中它不是..NET基于内存便宜的假设(通常是真的)


Tim*_*uri 6

如何大幅提高 C# 代码的性能

为此,每次你这样做时都会变得“不安全”(不受管理)someSortOfArray[i],.NET 框架都会执行各种需要时间的整洁事情(例如越界检查)。

这确实是非托管的全部意义(然后使用指针并执行 myPointer++)。

只是为了澄清,如果你不受管理,然后仍然做 afor-loop并做someArray[i],那么您什么也没有保存。

另一个可能对您有帮助的问题:True Unsafe Code Performance

免责声明

顺便说一句,我并不是说一直这样做,而是仅作为这个特定问题的答案。

  • JIT 可以跳过越界检查,因为它永远不会越界。 (3认同)