以下是c ++和c#中的两个代码部分完全相同:
#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;
}
时间:0.01s memmory:2576 kB
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);
}
}
}
时间:0.05s mem:38288 kB
如何改进C#代码以证明C#对我的同事来说可以和C ++一样快?
正如您所看到的,C#执行时间大5倍,内存消耗大15倍。
答案 0 :(得分:9)
在发布模式下编译并运行。在构建并在发布模式下运行时,我从C#版本获得0.01s。就内存消耗而言,您正在将苹果与橙子进行比较。托管环境将占用更多内存,因为它托管CLR和垃圾收集器,而这些内存并非免费。
答案 1 :(得分:6)
如何改进C#代码以证明C#对我的同事来说可以和C ++一样快?
你做不到。有一些合法的领域,C ++从根本上比C#更快。但也有一些领域,C#代码将比同等的C ++代码表现更好。他们是不同的语言,有不同的优点和缺点。
但作为程序员,你真的应该把你的决定建立在逻辑上。
逻辑规定您应首先收集信息,然后根据该信息做出决定。
相反,您决定首先,然后寻找支持它的信息。 如果你是一名政治家,那可能会奏效,但这不是编写软件的好方法。
不要去寻找C#比C ++更快的证据。相反,检查哪个选项在您的情况下更快 。
在任何情况下,如果你想证明X可以和Y一样快,你必须按照常规的方式去做:让X和Y一样快。和往常一样,在进行性能调整时,一个分析器就是你的最好的朋友。找出确切花费额外时间的地方,然后弄清楚如何消除它。
但内存使用是一个失败的原因。 .NET只使用更多内存,原因如下:
答案 2 :(得分:4)
为此做“不安全”(非托管)...每次你做someSortOfArray[i]
时,.NET框架都会做各种各样的事情(例如越界检查)准时。
这真的是非托管(然后使用指针和执行myPointer ++)的重点。
只是为了澄清,如果你不受管理,然后仍然做for-loop
并做someArray[i]
,你就什么都没有保存。
另一个S.O.可能有助于您的问题:True Unsafe Code Performance
顺便说一下,我并不是说要一直这样做,而是仅作为这个特定问题的答案。
答案 3 :(得分:3)
请注意您的时间安排。它没有显示,你是如何测量执行时间的。人们可以期待启动时.NET应用程序的合理开销。因此,如果您只关注循环的执行时间,则应该运行内部循环几次(多次),跳过1..2次迭代,测量其他迭代并计算平均值。
我希望结果比...更相似。但是,一如既往地针对“峰值性能” - 有关内存管理的预防措施非常重要。在这里,防止测量功能内部的“新”可能就足够了。在每次迭代中重用p []。
答案 4 :(得分:1)
内存使用量可能与垃圾回收有关。在Java中,内存使用量有意高 - 垃圾收集只在需要更多内存时才会发生。这是出于速度原因,因此C#做同样的事情是有意义的。您不应该在发布代码中执行此操作,但为了显示您实际使用的大量内存,可以在测量内存使用量之前调用GC.Collect()
。你真的关心它使用了多少内存吗?似乎速度更重要。如果你有内存限制,你可以设置程序在垃圾收集之前使用的内存量。