还是现在反过来了?
据我所知,c#在某些领域被证明比c++更快,但我从来没有勇气亲自测试它。
我想你们任何人都可以详细解释这些差异,或者告诉我有关信息的正确位置。
快了5个橘子。或者更确切地说:不可能有一个(正确的)笼统的答案。c++是一种静态编译语言(但也有配置文件引导的优化),c#在JIT编译器的帮助下运行。它们之间的差异如此之大,以至于像“快了多少”这样的问题都无法回答,甚至无法给出数量级。
没有严格的理由说明为什么基于字节码的语言(如c#或Java)不能像c++代码一样快。然而,c++代码在很长一段时间内都要快得多,今天在许多情况下仍然如此。这主要是因为更高级的JIT优化实现起来比较复杂,而真正酷的JIT优化现在才出现。
所以在很多情况下,c++更快。但这只是答案的一部分。c++实际上更快的情况是高度优化的程序,其中专业程序员彻底优化了代码。这不仅非常耗时(因此非常昂贵),而且由于过度优化通常会导致错误。
另一方面,使用解释语言编写的代码在运行时(。NET CLR或Java VM),不需要您做任何事情。JIT编译器可以做很多有用的优化,而这些在带有指针的语言中是不可能做到的。此外,一些人认为垃圾收集通常应该与手动内存管理一样快或更快,在许多情况下确实如此。你通常可以在c++或C中实现并实现所有这些,但这将更加复杂且容易出错。
正如Donald Knuth所说,“过早的优化是万恶之源”。如果你真的确定你的应用程序将主要由非常关键的性能算法组成,并且它将成为瓶颈,并且在c++中它肯定会更快,并且你确定c++不会与你的其他需求冲突,那么就选择c++。在任何其他情况下,首先集中精力用最适合您的语言正确地实现应用程序,然后如果运行太慢就找到性能瓶颈,然后考虑如何优化代码。在最坏的情况下,您可能需要通过外部函数接口调用C代码,因此您仍然可以用较低级别的语言编写关键部分。
请记住,优化一个正确的程序相对容易,但更正一个优化的程序要难得多。
给出实际的速度优势百分比是不可能的,这在很大程度上取决于你的代码。在许多情况下,编程语言实现甚至不是瓶颈。在http://benchmarksgame.alioth.debian.org/的基准测试中带着极大的怀疑,因为这些主要测试算术代码,这很可能与你的代码完全不相似。
通常,这取决于应用程序。在某些情况下,c#可能慢得可以忽略不计,而在其他情况下,c++要快5到10倍,特别是在操作可以轻松SIMD的情况下。
在一个特殊的场景中,c++仍然占据上风(并且将在未来几年占据上风),即可以在编译时预先确定多态决策。
通常,封装和延迟决策是一件好事,因为它使代码更加动态,更容易适应不断变化的需求,并且更容易作为框架使用。这就是为什么在c#中面向对象编程是非常高效的,并且它可以在术语“泛化”下泛化。不幸的是,这种特殊的泛化在运行时是有代价的。
通常,这个成本并不大,但在某些应用程序中,虚拟方法调用和对象创建的开销可能会产生影响(特别是因为虚拟方法阻止了其他优化,如方法调用内联)。这就是c++具有巨大优势的地方,因为你可以使用模板来实现一种不同类型的泛化,它对运行时有没有的影响,但并不一定比OOP的多态性少。事实上,所有构成OOP的机制都可以只用模板技术和编译时解析来建模。
在这种情况下(不可否认,它们通常局限于特殊的问题领域),c++胜过c#和类似的语言。
c++(或C)为您提供了对数据结构的细粒度控制。如果你想玩,你有这个选择。大型托管Java或. net应用程序(OWB, Visual Studio 2005年),使用Java/. net的内部数据结构。NET库自带包袱。我看到OWB设计器会话使用了超过400 MB的RAM,立方体或ETL设计的bid也达到了100 MB。
在可预测的工作负载上(例如重复一个过程多次的大多数基准测试),JIT可以为您提供优化得足够好的代码,没有实际差别。
在大型应用程序上,差异与其说是JIT,不如说是代码本身使用的数据结构。当应用程序的内存很重时,您将获得较低的缓存使用效率。在现代cpu上,缓存丢失是非常昂贵的。C或c++的真正优势在于,您可以优化数据结构的使用,从而更好地使用CPU缓存。
这是一个非常模糊的问题,没有真正明确的答案。
例如;我宁愿玩用c++而不是c#创建的3d游戏,因为性能肯定要好得多。(我知道XNA等,但它与真正的东西相去甚远)。
另一方面,如前所述;您应该使用一种能够让您快速完成所需工作的语言进行开发,并在必要时进行优化。
根据我的经验(这两种语言我都用过很多),与c++相比,c#的主要问题是内存消耗高,而且我还没有找到控制它的好方法。最终导致。net软件变慢的是内存消耗。
另一个因素是JIT编译器不能提供太多时间来进行高级优化,因为它在运行时运行,如果花费太多时间,最终用户会注意到它。另一方面,c++编译器有足够的时间在编译时进行优化。恕我直言,这个因素远没有内存消耗那么重要。
我知道这不是你要问的,但是c#通常比c++更快地写,这在商业环境中是一个很大的好处。
据我所知…
你的困难似乎在于决定你所听到的是否可信,当你试图评估这个网站上的回复时,这个困难将会重复。
你将如何判断人们在这里所说的比你最初听到的更可信还是更不可信?
一种方法是请求证据。
当有人声称“在某些领域c#被证明比c++快”问他们为什么他们这么说时,让他们给你看测量结果,让他们给你看程序。有时他们只是犯了一个错误。有时你会发现他们只是在表达一种观点,而不是分享一些他们可以证明是正确的事情。
通常情况下,信息和观点会混淆在人们的说法中,你必须试着分清哪个是哪个。例如,从这个论坛的回复中:
"采取基准在http://shootout.alioth.debian.org/ 带着极大的怀疑,如 这些主要测试算术代码, 哪一个最不相似 你的代码。" < / em > < / p > 扪心自问你是否真的 理解什么"这些很大程度上测试 算术代码"表示,然后 问问你自己,作者是否写过 实际上证明了他的主张是 李真的。< / p > < / > ”这是一个相当无用的测试,因为它实际上取决于你有多好 个别项目已经 优化;我已经设法加快了速度 有些是4-6倍甚至更多, 明确比较 之间的非优化方案是 而愚蠢的。" < / em > < / p > 问自己作者是否有 实际上向你展示了他的能力 “让其中一些加快4-6秒 倍或更多”——这是一个简单的说法!李< / p > < / >
”这是一个相当无用的测试,因为它实际上取决于你有多好 个别项目已经 优化;我已经设法加快了速度 有些是4-6倍甚至更多, 明确比较 之间的非优化方案是 而愚蠢的。" < / em > < / p > 问自己作者是否有 实际上向你展示了他的能力 “让其中一些加快4-6秒 倍或更多”——这是一个简单的说法!李< / p > < / >
我们有一个简单的基准来查看图形库的速度,那就是在窗口中随机绘制线条。c++ /GDI在处理10000行代码时仍然很灵活,而c# /Graphics在处理1000行代码时却很难做到。
毕竟,答案总要在某个地方,不是吗?:)
嗯,没有。
正如一些回复指出的那样,这个问题没有具体说明以一种邀请问题的方式来回应,而不是回答。只从一个方面来说:
然后是哪些项目?哪个机器?哪些操作系统?哪个数据集?
理论上,对于长期运行的服务器类型应用程序,jit编译的语言可以比本机编译的语言更快地变成多。由于JIT编译语言通常首先被编译为相当低级的中间语言,因此您可以在编译时进行大量高级优化。最大的优势在于,当JIT获得越来越多关于应用程序使用情况的数据时,它可以继续动态地重新编译代码段。它可以安排最常见的代码路径,以允许分支预测尽可能频繁地成功。它可以重新安排经常一起调用的独立代码块,以将它们都保存在缓存中。它可以花更多精力优化内部循环。
我怀疑。net或任何jre都能做到这一点,但早在我上大学的时候就有人在研究这一点,所以认为这类东西很快就会在现实世界中找到自己的方式也不是不合理的。
垃圾收集是Java#不能用于实时系统的主要原因。
GC什么时候会发生?
需要多长时间?
这是不确定的。
需要大量内存访问的应用程序。图像处理通常更适合在非托管环境(c++)而不是托管环境(c#)中编写。使用指针算法优化的内循环在c++中更容易控制。在c#中,你可能需要使用不安全的代码来获得相同的性能。
我们必须确定c#在性能上是否与c++相当,为此我写了一些测试程序(两种语言都使用Visual Studio 2005)。事实证明,如果没有垃圾收集,只考虑语言(而不是框架),c#的性能基本上与c++相同。c#中的内存分配比c++快得多,并且当数据大小超过缓存线边界时,c#在确定性方面略有优势。然而,所有这些最终都是要付出代价的,由于垃圾收集,c#的性能受到了不确定的影响,这是一个巨大的代价。
对于“令人尴尬的并行”问题,当在c++上使用Intel TBB和OpenMP时,我观察到与用c#和TPL处理的类似(纯数学)问题相比,性能大约提高了10倍。SIMD是c#无法竞争的一个领域,但我也有一个印象,TPL有相当大的开销。
也就是说,我只在性能关键的任务中使用c++,我知道我将能够多线程并快速得到结果。对于其他任何事情,c#(偶尔f#)都很好。
受此启发,我做了一个快速测试,使用了大多数程序所需的60%的通用指令。
下面是c#代码:
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(); }
字符串数组和数组列表是特意用来包含这些指令的。
下面是c++代码:
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(); }
我使用的输入文件大小是40 KB。
结果是
哦,但是这是在Linux上…c#在莫诺上运行…c++和g++。
好的,这是我在Windows上得到的Visual Studio 2003年:
. net语言可以像c++代码一样快,甚至更快,因为. net运行时必须为GC暂停,即使它对暂停非常聪明。
因此,如果你有一些代码必须持续快速运行,没有任何暂停,. net将引入延迟在某个时刻,即使你非常小心地使用运行时GC。
这要看情况。如果字节码被转换为机器代码(不仅仅是JIT)(我的意思是如果你执行程序)而且如果你的程序使用了许多分配/释放,它可能会更快,因为GC算法只需要通过整个内存一次(理论上),但正常的malloc/realloc/free C/ c++调用会在每次调用上引起开销(调用开销,数据结构开销,缓存丢失;))。
所以这在理论上是可能的(对于其他GC语言也是如此)。
对于大多数应用程序,我真的没有看到不能在c#中使用元编程的极端缺点,因为大多数程序员无论如何都不使用它。
另一个很大的优势是SQL,如LINQ“扩展”,为编译器提供了优化数据库调用的机会(换句话说,编译器可以将整个LINQ编译为一个“blob”二进制文件,其中所调用的函数是内联的或为您优化的,但我在这里只是推测)。
我已经在c++和c#中测试了vector - List和简单的2d数组。
vector
List
我使用Visual c# / c++ 2010 Express版本。这两个项目都是简单的控制台应用程序,我在标准(没有自定义设置)发布和调试模式下对它们进行了测试。 在我的电脑上,c#列表运行得更快,c#中的数组初始化也更快,数学运算更慢
我使用英特尔Core2Duo P8600@2.4GHz, c# - . net 4.0。
我知道向量实现不同于c#列表,但我只是想测试我将用于存储我的对象的集合(并能够使用索引访问器)。
当然,你需要清除内存(比如每次使用new),但我想保持代码简单。
new
c++矢量测试:
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#列表测试:
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); }
时间:(发布/调试)
c++
(是的,13秒,我总是在调试模式下遇到列表/向量的问题。)
c#:
C/ c++在有大型数组或数组(任何大小)上的大量循环/迭代的程序中可以表现得更好。这就是为什么在C/ c++中图形化通常要快得多,因为几乎所有的图形化操作都基于繁重的数组操作。net在数组索引操作中是出了名的慢,这是由于所有的安全检查,这对于多维数组尤其如此(是的,矩形c#数组甚至比锯齿形c#数组还要慢)。
如果你直接使用指针,避免Boost、std::vector和其他高级容器,以及inline每一个可能的小函数,那么C/ c++的好处就会最明显。尽可能使用老式数组。是的,你将需要更多的代码行来完成你在Java或c#中做的相同的事情,因为你避免了高级容器。如果你需要一个动态大小的数组,你只需要记住将你的new T[]与相应的delete[]语句配对(或使用std::unique_ptr);额外速度的代价是你必须更仔细地编码。但是作为交换,您可以摆脱托管内存/垃圾收集器的开销,这很容易占Java和. net中面向对象程序的执行时间的20%或更多,以及那些大量的托管内存数组索引成本。在某些特定的情况下,c++应用程序还可以从一些漂亮的编译器开关中受益。
std::vector
inline
new T[]
delete[]
std::unique_ptr
我是C、c++、Java和c#的编程专家。我最近难得地用后三种语言实现了完全相同的算法程序。这个程序有很多数学运算和多维数组运算。我在所有3种语言中都进行了大量优化。注意,c#程序只使用了安全代码;我的意见是,你最好在使用unsafe关键字之前用c++来编码。
unsafe
为了避免有人认为我反对c#,我将在结束时说c#可能是我最喜欢的语言。这是我迄今为止遇到的最符合逻辑、最直观、最快速的开发语言。我所有的原型都是用c#完成的。c#语言比Java有许多小而微妙的优势(是的,我知道微软有机会通过后期进入游戏并复制Java来修复Java的许多缺点)。有人为Java的Calendar类干杯吗?如果微软真的花精力去优化CLR和。net JITter, c#将会接管。说实话,我很惊讶他们在c#语言中做了这么多正确的事情,为什么不继续进行重磅的编译器优化呢?也许如果我们都乞求。
Calendar
我想这么说:编写更快代码的程序员,是那些更了解当前机器运行速度的人,顺便说一句,他们也是那些使用适当工具的人,这些工具允许精确的低级和确定性优化技术。由于这些原因,这些人使用C/ c++而不是c#。我甚至认为这是事实。
如果我没记错的话,c#模板是在运行时确定的。这肯定比c++的编译时模板慢。
当你考虑到很多人提到的所有其他编译时优化,以及安全性的缺失,确实意味着更高的速度……
我想说,就原始速度和最小内存消耗而言,c++是显而易见的选择。但这也转化为更多的时间来开发代码,并确保您不会泄漏内存或导致任何空指针异常。
结论:
c#:更快的开发,更慢的运行
c++:开发慢,运行快。
首先,我不同意这个问题的部分公认答案(并且得到了好评),我说:
在运行时用于jit代码的计算周期根据定义在程序执行中不可用。
运行时优化器的时间预算必然多比编译时优化器的时间预算更受约束(正如另一个评论者指出的那样)
底线:最终,你将几乎肯定能够在c++中创建比在c#中更快的实现。
现在,话虽如此,多快确实是不可量化的,因为有太多的变量:任务、问题领域、硬件、实现质量和许多其他因素。您将在您的场景上运行测试,以确定性能上的差异,然后决定是否值得额外的努力和复杂性。
这是一个很长很复杂的话题,但为了完整起见,我觉得值得一提的是,c#的运行时优化器非常出色,能够在运行时执行某些c++编译时(静态)优化器无法实现的动态优化。即使这样,优势通常仍然在本地应用程序的法院,但动态优化器是“几乎<强> < / >强 sure”的原因;上述限定词。
--
在相对性能方面,我也被我在其他一些答案中看到的数字和讨论所困扰,所以我想我应该插话,同时为我上面所做的陈述提供一些支持。
这些基准测试的很大一部分问题是,你不能像写c#一样写c++代码,并期望得到具有代表性的结果(例如。在c++中执行成千上万的内存分配将会给你可怕的数字。)
相反,我编写了稍微更习惯的c++代码,并与@Wiory提供的c#代码进行了比较。我对c++代码所做的两个主要更改是:
将2d数组平铺为1d以实现更好的缓存局部性(连续块)
c#(。净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#实现更改为相同的1d数组实现 生成Init: 40ms, Fill: 171ms, Total: 211ms ( c++仍然几乎 < / >强快40%)。< / p >
设计和编写“快速”要困难得多;在c++中编写“常规”的代码要容易得多。用任意一种语言编写代码。
归根结底,c++为您提供了对性能的更多控制。你想用指针吗?一个参考吗?栈内存?堆吗?动态多态还是用静态多态(通过模板/CRTP)消除虚表的运行时开销?在c++中你必须…呃,到达自己做出所有这些选择(和更多),理想情况下,这样你的解决方案就能最好地解决你正在处理的问题。
问问自己是否真的想要或需要该控件,因为即使对于上面的简单示例,您也可以看到尽管性能有了显著的改进,但它需要更深入的投资才能访问。
这实际上取决于你想在代码中实现什么。我听说这只是一个都市传说,VB和VB之间有性能上的差异。NET, c#和托管c++。然而,我发现,至少在字符串比较中,托管c++胜过c#,而c#又胜过VB.NET。
我并没有对这两种语言的算法复杂度做过详尽的比较。我也只是使用每种语言的默认设置。在VB。NET我使用设置要求声明变量,等等。下面是我用于托管c++的代码:(正如你所看到的,这段代码非常简单)。我用。net 4.6.2在Visual Studio 2013的其他语言中运行相同的程序。
#include "stdafx.h" using namespace System; using namespace System::Diagnostics; bool EqualMe(String^ first, String^ second) { return first->Equals(second); } int main(array<String ^> ^args) { Stopwatch^ sw = gcnew Stopwatch(); sw->Start(); for (int i = 0; i < 100000; i++) { EqualMe(L"one", L"two"); } sw->Stop(); Console::WriteLine(sw->ElapsedTicks); return 0; }
c#和c++在性能方面有一些主要的区别:
除此之外,程序员的能力也很重要。我见过一些糟糕的c++代码,其中的类通过值作为参数传递。在c++中,如果你不知道自己在做什么,实际上会让性能变差。
我发现2020年4月读到:https://www.quora.com/Why-is-C-so-slow-compared-to-Python由一个拥有15年以上软件开发经验的现实世界的程序员编写。
它指出,c#通常较慢,因为它被编译为通用中间语言,而不是像c++那样编译为机器代码。然后将CIL放入输出机器代码的公共语言运行库(CLR)。然而,如果你继续执行c#,它将接受机器代码的输出和缓存它,以便保存机器代码用于下次执行。总而言之,如果你多次执行c#可以更快,因为它是多次执行后的机器代码。
也有评论说,一个优秀的c++程序员可以做一些耗时的优化,但最终会被优化。
我在c++ vs c#中插入代码的一个领域是创建到SQL Server的数据库连接并返回结果集。我比较了c++ (ODBC上的薄层)和c# (ADO。NET SqlClient),并发现c++比c#代码快50%左右。ADO。NET被认为是处理数据库的低级接口。你可能会发现更大的差异是内存消耗而不是原始速度。
使c++代码更快的另一件事是,你可以在粒度级别上调优编译器选项,以一种在c#中无法做到的方式进行优化。