C ++比C#快多less?

还是现在呢?

据我所知,有一些C#certificate比C ++更快的领域,但是我从来没有胆量去亲自testing。

以为你们中的任何一个都可以详细解释这些差异,或者指出我对这方面信息的正确位置。

没有严格的原因,为什么像C#或Java这样的基于字节码的语言具有JIT不能像C ++代码那么快。 然而,C ++代码在很长一段时间内过去都是非常快的,而今天在很多情况下也是如此。 这主要是由于更高级的JIT优化实施起来很复杂,而且非常酷的只是刚刚到达。

所以C ++在很多情况下速度更快。 但这只是答案的一部分。 C ++实际上更快的情况是高度优化的程序,专家程序员彻底地从代码中彻底优化了程序。 这不仅非常耗时(并且因此很昂贵),而且由于过度优化而通常导致错误。

另一方面,在运行时的更高版本(.NET CLR或Java VM)中,解释型语言中的代码会变得更快,而无需执行任何操作。 有很多有用的优化JIT编译器可以做到这一点在指针的语言是根本不可能的。 另外,有些人认为垃圾收集一般应该像手动内存pipe理一样快或者更快,在很多情况下是这样。 您通常可以在C ++或C中实现和实现所有这些,但是这会变得更加复杂和容易出错。

正如唐纳德·克努特(Donald Knuth)所说:“不成熟的优化是万恶的根源”。 如果你真的知道你的应用程序将主要由性能关键algorithm组成,而且这将是瓶颈,并且在C ++中肯定会更快,并且你确信C ++不会和其他人发生冲突要求,去C ++。 在其他任何情况下,首先要以最适合您的任何语言来正确执行您的应用程序,然后在运行速度太慢时发现性能瓶颈,然后考虑如何优化代码。 在最糟糕的情况下,您可能需要通过外部函数接口调用C代码,所以您仍然可以使用低级语言编写关键部分。

请记住,优化一个正确的程序相对容易,但要更正优化的程序则要困难得多。

速度优势的实际百分比是不可能的,这主要取决于你的代码。 在许多情况下,编程语言的实现甚至不是瓶颈。 以http://benchmarksgame.alioth.debian.org/为基准,带着很大的怀疑,因为它们大部分testing算术代码,这很可能与您的代码很不相似。;

C#可能不会更快,但它会让你/我更快。 这是我所做的最重要的措施。 🙂

这是五个橙子更快。 或者说:不可能(正确)一揽子答案。 C ++是一种静态编译的语言(但是后来也有configuration文件引导优化),JIT编译器帮助C#运行。 有这么多的差异,像“多快”这样的问题是不能回答的,甚至不能提供数量级。

根据我的经验(我已经在这两种语言上工作过很多),与C ++相比,C#的主要问题是内存消耗高,而且我还没有find控制它的好方法。 内存消耗最终会减慢.NET软件的速度。

另一个因素是JIT编译器不能承担太多的时间来执行高级优化,因为它在运行时运行,而最终用户会花费太多时间来注意它。 另一方面,C ++编译器总是需要在编译时进行优化。 这个因素比内存消耗更less,恕我直言。

C ++仍然占据优势的一个特定场景是,当编译时可以预先确定多态决策时,就会出现这种情况。

一般来说,封装和延期决策是一件好事,因为它使代码更加dynamic,更容易适应不断变化的需求,更容易作为一个框架使用。 这就是为什么C#中的面向对象编程非常高效,可以在“泛化”这个术语下推广。 不幸的是,这种特殊的泛化在运行时是有代价的。

通常,这个成本是非实质性的,但有一些应用程序虚拟方法调用和对象创build的开销可以有所作为(特别是因为虚拟方法阻止其他优化,如方法调用内联)。 这就是C ++具有巨大优势的地方,因为您可以使用模板来实现对运行时没有影响的generics化,但不一定比OOP更less。 实际上,所有构成OOP的机制都可以仅使用模板技术和编译时parsing来build模。

在这种情况下(不可否认,它们经常被限制在特殊的问题领域),C ++可以胜过C#和可比较的语言。

我将首先不同意这个问题的一部分接受(和高度回答)的回答,并指出:

实际上,为什么JITted代码运行速度慢于经过适当优化的C ++(或其他没有运行时间开销的语言)程序,其中有很多原因,包括:

  • 在运行时花费在JITting代码上的计算周期在程序执行中定义是不可用的。

  • JITter中的任何热path将与您的代码竞争CPU中的指令和数据caching。 根据定义,我们知道caching在性能和本地语言(如C ++)中占主导地位,并没有这种types的争用。

  • 运行时优化器的时间预算必然比编译时优化器的约束严格得多(正如另一位评论者所指出的那样)

底线:最终,您几乎可以肯定能够在C ++中创build比C#更快的实现

现在,就这么说,实际上无法量化的速度有多快 ,因为variables太多:任务,问题域,硬件,实施质量等诸多因素。 您将对您的scheme进行testing,以确定额外的努力和复杂性是否值得。

这是一个非常漫长而复杂的话题,但是为了完整起见,我觉得值得一提的是C#的运行时优化器非常出色,并且能够在运行时执行某些dynamic优化,而这些dynamic优化在C ++编译时根本无法使用(静态)优化器。 即使如此,优势在本地应用程序的法庭中通常仍然很深,但dynamic优化器是上面给出的“ 几乎肯定”限定词的原因。

就相对performance而言,我还对其他答案中看到的数字和讨论感到不安,所以我想我会同时提出一些支持。

这些基准testing的很大一部分问题是,你不能像编写C#那样编写C ++代码,并希望得到具有代表性的结果(例如,在C ++中执行数千个内存分配会给你带来可怕的数字)。

相反,我写了稍微更习惯的C ++代码,并与@Wiory提供的C#代码进行了比较。 我对C ++代码做了两个重大的改变:

1)使用了vector :: reserve()

2)将2d数组展平为1d,以获得更好的caching局部性(连续块)

C#(.NET 4.6.1)

 private static void TestArray() { const int rows = 5000; const int columns = 9000; DateTime t1 = System.DateTime.Now; double[][] arr = new double[rows][]; for (int i = 0; i < rows; i++) arr[i] = new double[columns]; DateTime t2 = System.DateTime.Now; Console.WriteLine(t2 - t1); t1 = System.DateTime.Now; for (int i = 0; i < rows; i++) for (int j = 0; j < columns; j++) arr[i][j] = i; t2 = System.DateTime.Now; Console.WriteLine(t2 - t1); } 

运行时间(释放):初始值:124ms,填充:165ms

C ++ 14(Clang v3.8 / C2)

 #include <iostream> #include <vector> auto TestSuite::ColMajorArray() { constexpr size_t ROWS = 5000; constexpr size_t COLS = 9000; auto initStart = std::chrono::steady_clock::now(); auto arr = std::vector<double>(); arr.reserve(ROWS * COLS); auto initFinish = std::chrono::steady_clock::now(); auto initTime = std::chrono::duration_cast<std::chrono::microseconds>(initFinish - initStart); auto fillStart = std::chrono::steady_clock::now(); for(auto i = 0, r = 0; r < ROWS; ++r) { for (auto c = 0; c < COLS; ++c) { arr[i++] = static_cast<double>(r * c); } } auto fillFinish = std::chrono::steady_clock::now(); auto fillTime = std::chrono::duration_cast<std::chrono::milliseconds>(fillFinish - fillStart); return std::make_pair(initTime, fillTime); } 

运行时间(释放):初始化:398μs(是,这是微秒),填充:152ms

总运行时间:C#:289ms,C ++ 152ms(大约快90%)

意见

  • 将C#实现更改为同一个1d数组实现,结果为:初始值:40ms,填充:171ms,总计:211ms( C ++仍然快了近40% )。

  • 在C ++中devise和编写“快速”代码比用任何一种语言编写“规则”代码要困难得多。

  • 在C ++中可能(使用)可能非常容易; 我们看到,与毫无保留的载体性能。 还有很多像这样的陷阱。

  • 当你考虑运行时发生的所有事情时,C#的性能是相当惊人的。 而且这个performance比较容易获得。

  • 比较C ++和C#性能的更多轶事数据: https : //benchmarksgame.alioth.debian.org/u64q/compare.php?lang=gpp&lang2=csharpcore

底线是C ++给你更多的性能控制。 你想用指针吗? 参考? 堆栈内存? 堆? dynamic多态或消除具有静态多态的vtable的运行时间开销(通过模板/ CRTP)? 在C ++中,您必须…呃, 自己做出所有这些select(更多),理想的是让您的解决scheme最好地解决您正在处理的问题。

问问你自己是否真的需要或者需要这种控制,因为即使是上面这个微不足道的例子,你也可以看到虽然性能有了显着的提高,但是需要更深入的投资才能获得。

C ++(或者C就可以)为您提供对数据结构的精细控制。 如果你想咬一口,你有这个select。 大型托pipe的Java或.NET应用程序(OWB, Visual Studio 2005 )使用Java / .NET库的内部数据结构,随身携带着行李。 我已经看到OWBdevise者会话使用了超过400 MB的RAM和BIDS,用于立方体或ETLdevise进入百兆的MB。

在一个可预测的工作负载上(比如大多数重复一个进程的基准testing),一个JIT可以让你的代码被优化得足够好,没有实际的区别。

国际海事组织(IMO)在大型应用程序上的差别不在于代码本身使用的数据结构。 如果应用程序内存繁重,则caching使用效率会降低。 在现代CPU上的高速caching未命中是非常昂贵的。 在C或C ++真正赢的地方,你可以在哪里优化你的数据结构的使用,以便与CPUcaching很好的搭配。

对于graphics来说,标准的C#graphics类比通过C / C ++访问的GDI要慢。 我知道这与语言本身无关,更多的是.NET平台,但是graphics是作为GDI替代品提供给开发者的,它的性能非常糟糕,我甚至不敢做graphics用它。

我们有一个简单的基准,我们使用它来看graphics库有多快,而这只是在窗口中绘制随机线。 C ++ / GDI仍然有10000行,而C#/ Graphics实时难以做1000。

垃圾收集是Java#不能用于实时系统的主要原因。

  1. GC何时会发生?

  2. 这需要多长时间?

这是非确定性的。

我们必须确定C#在性能上是否与C ++相当,并且为此编写了一些testing程序(对于这两种语言都使用Visual Studio 2005)。 事实certificate,没有垃圾收集,只考虑语言(不是框架),C#与C ++有基本相同的性能。 内存分配在C#中的速度比在C ++中快得多,而当数据大小超出高速caching行边界时,C#在确定性方面略有优势。 然而,所有这些最终都要付钱,并且由于垃圾收集,C#的非确定性性能命中的forms是巨大的代价。

像往常一样,这取决于应用程序。 有些情况下,C#可能会慢得多,其他情况下C ++的速度要快5到10倍,特别是在操作可以很容易SIMD的情况下。

我知道这不是你所要求的,但是C#通常比C ++更快,这在商业环境中是一个巨大的奖励。

这是一个非常模糊的问题,没有真正的明确答案。

例如; 我宁愿玩用C ++创build的3D游戏,因为性能肯定要好很多。 (而且我知道XNA等等,但它没有办法靠近真实的东西)。

另一方面,如前所述, 你应该开发一种语言,让你快速做你想做的事情,然后在必要时进行优化。

>从我听到的…

你的难处似乎在于判断你所听到的是否可信,而当你试图评估本网站的回复时,这种困难就会重演。

你怎么去决定人们在这里所说的话是否比你最初听到的更可信?

一种方法是要求证据

当有人声称“有一些C#certificate比C ++更快的领域”时, 问他们为什么这么说 ,要求他们向你展示测量结果,让他们向你展示程序。 有时他们只会犯了一个错误。 有时你会发现他们只是在expression意见,而不是分享他们可以certificate是真实的东西。

信息和意见往往会混淆在人们所声称的内容中,而你必须尝试理清哪个是哪个。 例如,从这个论坛回复:

.NET语言可以像C ++代码一样快,甚至更快, 但是C ++代码将具有更恒定的吞吐量,因为.NET运行时必须暂停GC ,即使它在暂停时非常聪明。

所以,如果你有一些代码需要一直运行得很快而没有任何停顿,那么即使你对运行时GC非常小心,.NET也会在某个时候引入延迟。

理论上,对于长时间运行的服务器types的应用程序,JIT编译的语言可能比本地编译的语言快得多。 由于JIT编译语言通常首先编译为相当低级的中间语言,因此无论如何您都可以在编译时进行大量的高级优化。 JIT可以继续重新编译代码段,因为它可以获得越来越多的关于如何使用应用程序的数据。 它可以安排最常见的代码path,以允许分支预测尽可能经常成功。 它可以重新安排单独的代码块,这些代码块通常被称为一起保存在caching中。 它可以花费更多的精力来优化内部循环。

我怀疑这是由.NET还是任何JRE完成的,但是当我上大学的时候正在研究这个问题,所以认为这些事情可能很快就会在现实世界中进入到现实中并不是不合理的。

需要密集存储器访问的应用程序 在非托pipe环境(C ++)中编写图像操作通常比托pipe(C#)编写的更好。 使用指针algorithm优化内部循环在C ++中更容易控制。 在C#中,您可能需要使用不安全的代码才能获得接近相同的性能。

对于'尴尬的并行'问题,当在C ++上使用英特尔TBB和OpenMP时,与C#和TPL类似的(纯math)问题相比,我观察到性能提高了大约10倍。 SIMD是C#无法竞争的一个领域,但是我也得到了TPL有相当大的开销的印象。

也就是说,我只使用C ++进行性能关键任务,我知道我将能够快速multithreading并获得结果。 对于其他一切,C#(偶尔F#)就好了。

C / C ++可以在大型数组或任何大小的数组上进行循环/迭代的程序中执行得更好。 这就是在C / C ++中graphics通常要快得多的原因,因为繁重的数组操作是几乎所有graphics操作的基础。 由于所有的安全检查,.NET在数组索引操作方面声名狼借,对于multidimensional array(尤其是长方形的C#数组甚至比锯齿形的C#数组更慢),情况尤其如此。

如果直接使用指针并避免使用Boost, std::vector和其他高级容器,以及inline每个小函数,则C / C ++的奖金最为明显。 尽可能使用旧式的数组。 是的,您将需要更多的代码行来完成您在Java或C#中所做的相同的事情,因为您避免使用高级容器。 如果你需要一个dynamicresize的数组,你只需要记住将你的new T[]与相应的delete[]语句(或者使用std::unique_ptr )进行配对 – 额外速度的代价是你必须更仔细地编码。 但作为交换,您可以摆脱托pipe内存/垃圾收集器的开销,这很容易成为Java和.NET中大量面向对象程序的执行时间的20%或更多,以及那些大规模托pipe内存数组索引成本。 在某些特定情况下,C ++应用程序也可以从一些漂亮的编译器开关中受益。

我是C,C ++,Java和C#的专家程序员。 最近我有一个难得的机会来实现在后三种语言中完全相同的algorithm程序。 该程序有很多math和multidimensional array操作。 我用这三种语言进行了大量的优化。 结果是我通常在不太严格的比较中看到的典型结果:Java的速度比C#快大约1.3倍(大多数JVM比CLR更优化),C ++原始指针版本比C#快2.1倍。 请注意,C#程序只使用安全代码 – 这是我的意见,你可能还需要在使用unsafe关键字之前用C ++编写代码。

为了避免有人认为我对C#有什么反对意见,我会说C#可能是我最喜欢的语言。 这是迄今为止我遇到的最合乎逻辑,直观和快速的开发语言。 我用C#做所有的原型。 C#语言与Java有许多小的,微妙的优势(是的,我知道微软有机会通过迟到进入游戏并可以复制Java来解决许多Java的缺点)。 敬酒到Java的Calendar类任何人? 如果微软真的花费精力来优化CLR和.NET JITter,C#可以认真接pipe。 我真的很惊讶,他们还没有 – 他们在C#语言中做了很多事情,为什么不跟着重击编译器优化呢? 也许如果我们都乞求。

我已经testing了C ++和C#中的vectorList和简单的二维数组。

我正在使用Visual C#/ C ++ 2010 Express版本。 这两个项目都是简单的控制台应用程序,我已经在标准(无自定义设置)版本和debugging模式下进行了testing。 C#列表在我的电脑上运行得更快,C#中的数组初始化也更快,math运算速度更慢。

我使用的是Intel Core2Duo P8600@2.4GHz,C# – .NET 4.0。

我知道vector实现不同于C#列表,但我只是想testing集合,我将用来存储我的对象(并能够使用索引访问器)。

当然,你需要清除内存(假设每次使用new内存),但是我想保持代码简单。

C ++vectortesting

 static void TestVector() { clock_t start,finish; start=clock(); vector<vector<double>> myList=vector<vector<double>>(); int i=0; for( i=0; i<500; i++) { myList.push_back(vector<double>()); for(int j=0;j<50000;j++) myList[i].push_back(j+i); } finish=clock(); cout<<(finish-start)<<endl; cout<<(double(finish - start)/CLOCKS_PER_SEC); } 

C#列表testing:

 private static void TestVector() { DateTime t1 = System.DateTime.Now; List<List<double>> myList = new List<List<double>>(); int i = 0; for (i = 0; i < 500; i++) { myList.Add(new List<double>()); for (int j = 0; j < 50000; j++) myList[i].Add(j *i); } DateTime t2 = System.DateTime.Now; Console.WriteLine(t2 - t1); } 

C ++ – 数组:

 static void TestArray() { cout << "Normal array test:" << endl; const int rows = 5000; const int columns = 9000; clock_t start, finish; start = clock(); double** arr = new double*[rows]; for (int i = 0; i < rows; i++) arr[i] = new double[columns]; finish = clock(); cout << (finish - start) << endl; start = clock(); for (int i = 0; i < rows; i++) for (int j = 0; j < columns; j++) arr[i][j] = i * j; finish = clock(); cout << (finish - start) << endl; } 

C# – 数组:

 private static void TestArray() { const int rows = 5000; const int columns = 9000; DateTime t1 = System.DateTime.Now; double[][] arr = new double[rows][]; for (int i = 0; i < rows; i++) arr[i] = new double[columns]; DateTime t2 = System.DateTime.Now; Console.WriteLine(t2 - t1); t1 = System.DateTime.Now; for (int i = 0; i < rows; i++) for (int j = 0; j < columns; j++) arr[i][j] = i * j; t2 = System.DateTime.Now; Console.WriteLine(t2 - t1); } 

时间:(释放/debugging)

C ++

  • 600/606 msarrays初始化,
  • 200/270毫秒数组填充,
  • 1秒/ 13秒vector初始化和填充。

(是的,13秒,在debugging模式下,我总是遇到列表/向量的问题。)

C#:

  • 20/20arrays初始化,
  • 403/440毫秒数组填充,
  • 710/742毫秒列表初始化和填充。

我会这么说:编写更快代码的程序员是那些更了解当前机器运行速度的人,而且他们也是使用合适的工具来精确确定低级和确定性的工具优化技术。 由于这些原因,这些人是使用C / C ++而不是C#的人。 我甚至会说这是一个事实。

如果我没有弄错,C#模板是在运行时确定的。 这必须比编译C ++的时间模板慢。

而当你采取所有其他的编译时优化,以及缺乏安全性,确实意味着更多的速度…

我想说C ++是原始速度和最小内存消耗的明显select。 但是这也意味着需要更多的时间来开发代码,并确保不会泄漏内存或导致任何空指针exception。

判决:

  • C#:开发速度更快,运行速度更慢

  • C ++:开发速度慢,运行速度快。

我猜想用C#编写的应用程序运行速度很快,而且还有更多的C ++编写的应用程序运行速度很快(C ++只是老一点…而且也是以UNIX为例)
– 问题的确是 – 用户和开发人员抱怨的是…
那么,恕我直言,在C#的情况下,我们有非常舒适的用户界面,非常好的层次结构的图书馆,以及CLI的整个接口系统。 在C ++的情况下,我们有模板,ATL,COM,MFC以及像OpenGL,DirectX等已经编写和运行的代码的整个shebang …开发人员抱怨C#的情况下GC调用不确定升级(意味着程序运行速度快,在一秒钟内 – 砰!它卡住了)。
在C#中编写代码非常简单和快速(不要忘记,这也增加了错误的机会。对于C ++,开发人员抱怨内存泄漏, – 意味着压缩,DLL之间的调用,以及“DLL地狱”问题支持和更新的图书馆…
我认为在编程语言中你将拥有更多的技能,质量(和速度)就越能表征你的软件。

这得看情况。 If the byte-code is translated into machine-code (and not just JIT) (I mean if you execute the program) and if your program uses many allocations/deallocations it could be faster because the GC algorithm just need one pass (theoretically) through the whole memory once, but normal malloc/realloc/free C/C++ calls causes an overhead on every call (call-overhead, data-structure overhead, cache misses 😉 ).

So it is theoretically possible (also for other GC languages).

I don't really see the extreme disadvantage of not to be able to use metaprogramming with C# for the most applications, because the most programmers don't use it anyway.

Another big advantage is that the SQL, like the LINQ "extension", provides opportunities for the compiler to optimize calls to databases (in other words, the compiler could compile the whole LINQ to one "blob" binary where the called functions are inlined or for your use optimized, but I'm speculating here).

> After all, the answers have to be somewhere, haven't they? 🙂

Umm, no.

As several replies noted, the question is under-specified in ways that invite questions in response, not answers. To take just one way:

  • the question conflates language with language implementation – this C program is both 2,194 times slower and 1.17 times faster than this C# program – we would have to ask you: Which language implementations?

And then which programs? Which machine? Which OS? Which data set?

Inspired by this, I did a quick test with 60 percent of common instruction needed in most of the programs.

Here's the C# code:

 for (int i=0; i<1000; i++) { StreamReader str = new StreamReader("file.csv"); StreamWriter stw = new StreamWriter("examp.csv"); string strL = ""; while((strL = str.ReadLine()) != null) { ArrayList al = new ArrayList(); string[] strline = strL.Split(','); al.AddRange(strline); foreach(string str1 in strline) { stw.Write(str1 + ","); } stw.Write("\n"); } str.Close(); stw.Close(); } 

String array and arraylist are used purposely to include those instructions.

Here's the c++ code:

 for (int i = 0; i<1000; i++) { std::fstream file("file.csv", ios::in); if (!file.is_open()) { std::cout << "File not found!\n"; return 1; } ofstream myfile; myfile.open ("example.txt"); std::string csvLine; while (std::getline(file, csvLine)) { std::istringstream csvStream(csvLine); std::vector csvColumn; std::string csvElement; while( std::getline(csvStream, csvElement, ',') ) { csvColumn.push_back(csvElement); } for (std::vector::iterator j = csvColumn.begin(); j != csvColumn.end(); ++j) { myfile << *j << ", "; } csvColumn.clear(); csvElement.clear(); csvLine.clear(); myfile << "\n"; } myfile.close(); file.close(); } 

The input file size I used was 40 KB.

And here's the result –

  • C++ code ran in 9 seconds.
  • C# code: 4 seconds!!!

Oh, but this was on Linux… With C# running on Mono … And C++ with g++.

OK, this is what I got on Windows – Visual Studio 2003 :

  • C# code ran in 9 seconds.
  • C++ code – horrible 370 seconds!!!