大型阵列的C#内存优化 这里有C++和C语言中的两个代码部分:绝对相同:

大型阵列的C#内存优化 这里有C++和C语言中的两个代码部分:绝对相同:,c#,c++,optimization,performance,C#,C++,Optimization,Performance,C++ #包括 int main(int argc,char*argv[]){ charp[1000000]; 无符号整数i,j; 无符号长s=0; 对于(i=2;i在发布模式下编译和运行。当在发布模式下构建和运行时,我从C#版本中获得了0.01秒。就内存消耗而言,您正在将苹果和橙子进行比较。托管环境将消耗更多内存,因为它托管CLR和垃圾收集器,而这些都不是免费提供的。内存使用率可能与垃圾收集有关。在Java中,内存使用率故意很高——垃圾收集只在需要更多内存时发生。这是出于速度原因,因此C#做

C++

#包括
int main(int argc,char*argv[]){
charp[1000000];
无符号整数i,j;
无符号长s=0;

对于(i=2;i在发布模式下编译和运行。当在发布模式下构建和运行时,我从C#版本中获得了0.01秒。就内存消耗而言,您正在将苹果和橙子进行比较。托管环境将消耗更多内存,因为它托管CLR和垃圾收集器,而这些都不是免费提供的。

内存使用率可能与垃圾收集有关。在Java中,内存使用率故意很高——垃圾收集只在需要更多内存时发生。这是出于速度原因,因此C#做同样的事情是有道理的。在发布代码中不应该这样做,但为了显示实际使用的内存,可以调用
GC.Collect()
在测量内存使用量之前。您真的关心它使用了多少内存吗?速度似乎更重要。如果您有内存限制,您可能可以在垃圾收集之前设置程序将使用的内存量

<> P>我如何改进C代码来证明C++的C可以和我的同事一样快? 有一些合法的地方,C++的基本上比C语言快。但是还有一些区域C代码比等效C++代码更好。它们是不同的语言,有不同的长处和弱点。 但是作为一个程序员,你真的应该把你的决定建立在逻辑的基础上

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

相反,你先做了决定,然后寻找支持它的信息。 如果你是一个政客,这可能会奏效,但这不是编写软件的好方法

<>不要去寻找证明C++比C++更快的证据,而是检查你的选项在你的情况下是哪个更快。 在任何情况下,如果你想证明X可以和Y一样快,你必须用通常的方法:使X和Y一样快。而且,一如既往,在进行性能调整时,探查器是你最好的朋友。找出额外时间的确切位置,然后找出如何消除它

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

  • 它有一个更大的运行库,必须存在于进程的地址空间中
  • .NET对象有不存在于C++类中的附加成员,因此它们使用更多的内存
  • 垃圾回收器意味着你通常会有一些“不再使用但尚未回收”的内存在周围。在C++中,内存通常是立即释放的。在.NET中,它不是。.NET是基于内存便宜(通常是真的)
  • 的假设。
如何大大提高C代码的性能 为此,请选择“不安全”(非托管)…每次您执行
sometortofarray[i]
时,.NET framework都会执行各种占用时间的整洁操作(例如越界检查)

这就是非托管(然后使用指针并执行myPointer++)的真正意义所在

只是想澄清一下,如果您处于非托管状态,然后仍然执行
for循环
someArray[i]
,那么您没有保存任何内容

另一个S.O.问题可能会帮助您:

免责声明
顺便说一句,我并不是说要一直这样做,只是为了回答这个特定的问题。

只是一个关于计时的注释。没有显示,您是如何测量执行时间的。可以预期.NET应用程序在启动时会有合理的开销。因此,如果您只关心循环的执行时间,您应该运行内部循环数次(多次),跳过1..2次第一次迭代,测量其他迭代并计算平均值


我希望结果比更相似。但是,与往常一样,当目标为“峰值性能”时,有关内存管理的预防措施很重要。在这里,它可能足以防止度量函数中出现“新”的情况。重用p[]在每次迭代中。

在深入研究之前,可能需要注意一些东西:数组是不同的。C/C++示例中的数组在堆栈上。在C#中,它在堆上。C#中的
i
j
变量占用的空间更大,如果是32位处理器,处理器可能需要更多的努力才能使用r、 使用
uint
,假设(公平地考虑迭代量)
unsigned int
在C/C++示例中为4字节。
p[0]
p[1]
在C/C++示例中是未初始化的,因此是有问题的,但在C#示例中是
0
。加上
s
在C#示例中是
double
,在C/C++示例中是
ulong
(有效地)。整数算法实际上总是比浮点更快。“C++代码示例”你的一本书是用纯C语言写的。所以在证明任何东西之前,先学习一些东西可能会有帮助。你没有花时间印刷,是吗?这不算什么P@pickypg:更不用说更不容易出错了。@Dimitry:正如你所看到的,这两个人做的并不是“完全相同的事情”,只有类似的事情。JIT可以跳过越界检查,因为它从不越界。我可以在堆栈上分配1MB数组吗?并从中获取数据吗?@Dmitry:有(可能是C规范中唯一提到人们一直在谈论的“堆栈”的地方:)。如果堆栈上有一个meg可用,则可以。@Martinho-32位抖动仅在某些情况下消除边界检查。例如,如果将数组的长度存储在局部变量中,然后对照该局部变量检查循环变量,则将执行边界检查。在这种情况下,64位抖动的行为不同gard(带l
#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;
}
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);
        }
    }
}