C++比C#快多少?

315

还是说现在情况反过来了?

据我所知,有些领域 C# 比 C++ 更快,但我从未有勇气自己测试。

希望您能详细解释这些差异或指导我获取相关信息。


9
为了防止发布更多随意的基准测试结果,进行了保护。如果你认为你有说服力,你需要10个声望来证明。 - Robert Harvey
1
这几乎是一个无关紧要的问题,因为我们生活在一个可以将IL转换为CPP并从那里进行优化的时代:https://docs.unity3d.com/Manual/IL2CPP.html - pixelpax
检查数组越界访问的语言永远不会比没有这种检查的语言表现更好。 - Seva Alekseyev
@SevaAlekseyev 这不是语言造成的,而是编译器造成的。除了明显的原因之外,C++之所以如此快,其中一个原因在于C++编译器已经存在了过去35年(如果不是更长时间)。没有什么能阻止C#编译器随着时间的推移变得更好。对于您提到的情况,请阅读这篇文章https://dev59.com/5WQn5IYBdhLWcg3wmIAs。 - Trap
29个回答

3
如果我没记错的话,C#模板是在运行时确定的。这比C++的编译时模板要慢。此外,考虑到其他许多编译时优化以及缺乏安全性所带来的更高速度... 我认为从原始速度和最小内存消耗方面来看,C++是显而易见的选择。但这也意味着需要更多时间来开发代码并确保不会泄漏内存或导致任何空指针异常。
结论:
- C#: 开发快,运行慢。 - C++: 开发慢,运行快。

3
我找到了这篇2020年4月的文章:https://www.quora.com/Why-is-C-so-slow-compared-to-Python,作者是一位有15年以上软件开发经验的实际程序员。文章指出,通常情况下C#较慢是因为它被编译成了公共中间语言(CIL)而不是像C++一样被编译成机器码。然后,CIL会通过公共语言运行时(CLR)输出机器码。但是,如果你反复执行C#代码,它将保存机器码的输出结果,并进行缓存,以便下次执行时可以直接使用机器码,从而使C#变得更快。

此外,还有评论称,优秀的C++程序员可以进行耗时的优化,最终得到优化后的代码。

C#并不比Python慢。我编写了一个简单的测试程序,创建了一个大小为102410248的字节数组,然后用索引%255填充它,在Python中需要1.4秒,在C#中只需要45毫秒(第一次执行,而不是多次运行后)。此外,问题是C++比Python快多少,而不是C#。 - GoldenretriverYT
Quora的答案包含许多意见,但很少有真正的知识。Python的性能甚至不接近C#,C ++或任何编译语言。此外,无论作者描述感知性能差异的“原因”是什么,都不理解中间编译的工作方式,也不知道Python做了类似的事情。 - Charles Burns

2
好的,这取决于情况。如果将字节码翻译成机器码(而不仅仅是JIT)(我是指执行程序),并且如果您的程序使用许多分配/释放,则可能更快,因为GC算法只需要一次通过整个内存(理论上),但正常的malloc/realloc/free C/C++调用会在每次调用时产生开销(调用开销,数据结构开销,缓存未命中;)。

因此,从理论上讲,这对于其他GC语言也是可能的。

我真的看不出在大多数应用程序中无法使用C#进行元编程的极端劣势,因为大多数程序员都不使用它。

另一个重要的优势是,像 LINQ “扩展” 一样,SQL 提供了编译器优化对数据库调用的机会(换句话说,编译器可以将整个 LINQ 编译为一个“blob”二进制文件,在其中内联或针对您的使用进行优化,但我这里只是在推测)。

2
任何合格的C++开发人员都不会遇到您所描述的问题。只有将类加入到他们的程序中并称其为C++的糟糕C程序员才会遇到这些问题。 - Clearer
1
天哪,这已经8年了,我的天啊 - Quonux
随意提供更好、更实时的答案。 - Quonux
我们还应该考虑C++的编译时元编程能力,这使得开发人员能够在编译时执行代码片段。需要注意的是,现代C++更像带有模板的C语言。与面向对象编程相比,它更倾向于函数式编程。constexp的引入使得元编程更易于阅读和编写。 - user982042

2
我会这样表述:编写更快代码的程序员,是那些更了解当前计算机如何快速运行的人,顺便他们也是使用适当工具进行精确低级别和确定性优化技术的人。出于这些原因,这些人使用C/C++而不是C#。我甚至可以说这是事实。

Notch编写的Minecraft在考虑到他所处理的数据量时运行速度相当快。此外,他几乎是独自编写了它,在相对较短的时间内完成了这项工作,而这在C++中几乎是不可能的。我确实同意优化技术——如果你有额外的10倍开发时间来使你的代码运行速度提高两倍,那么这可能是值得的。 - Bill K

2

我认为有些用C#编写的应用程序运行速度很快,同样也有更多用C++编写的应用程序运行速度很快(毕竟C++比较老...UNIX也是如此...)
- 问题确实在于 - 用户和开发人员抱怨的是什么...
在我看来,对于C#,我们有非常舒适的用户界面,非常漂亮的库层次结构,以及整个CLI接口系统。对于C++,我们有模板,ATL,COM,MFC以及OpenGL,DirectX等已经编写和运行的代码的整个系列...开发人员抱怨C#中GC调用不确定地增加(意味着程序运行很快,然后在一秒钟内 - 突然卡住了)。
使用C#编写代码非常简单快捷(不要忘记这也增加了错误的机会)。对于C++,开发人员抱怨内存泄漏,即崩溃,DLL之间的调用,以及“DLL hell” - 支持和替换新库的问题...
我认为你在编程语言方面的技能越高,你的软件就越具有质量(和速度)。


2
我在C++和C#中的代码实现方面,特别是在创建与SQL Server的数据库连接并返回结果集时进行了测量。比较了基于ODBC的C++和基于ADO.NET SqlClient的C#,发现C++比C#快约50%。ADO.NET被认为是处理数据库的低级接口。你可能会看到更大的区别在于内存消耗,而不是原始速度。
另一个使C++代码更快的因素是你可以在编译器选项上进行细致的调整,以一种无法在C#中实现的方式进行优化。

1
这真的取决于你在代码中想要实现什么。我听说过,在VB.NET、C#和managed C++之间没有任何性能差异只是一个城市传说。然而,至少在字符串比较方面,我发现managed C++比C#效率更高,而C#又比VB.NET更高效。
我并没有在语言之间进行算法复杂度的详尽比较。我也只是使用每种语言的默认设置。在VB.NET中,我使用了变量声明等设置。以下是我在managed C++中使用的代码:(正如你所看到的,这段代码非常简单)。我在Visual Studio 2013中以.NET 4.6.2运行其他语言的相同代码。
#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;
}

1

> 毕竟,答案肯定某处存在,不是吗? :)

嗯,不是这样的。

正如几个回复所指出的那样,问题缺乏明确说明,会引发更多的问题,而非答案。仅以一种方式为例:

  • 该问题混淆了语言和语言实现——这个 C 程序比 this C# 程序194倍, 但比它快1.17倍 - 我们必须询问您:哪种语言实现?

然后是哪些程序?哪台机器?使用哪个操作系统?哪个数据集?


我完全同意。我想知道为什么人们在问一个普遍性问题时,期望得到一个精确的答案(63.5%)。我认为这种问题没有一个普适的答案。 - call me Steve
@callmesteve:我知道你的意思,但是你最后一句话听起来对于任何程序员来说都像是在用指甲刮黑板。 - Wouter van Nifterick
1
这似乎并没有回答问题,更像是一条评论或抱怨。 - Tas

-14
受到这个的启发,我做了一个快速测试,涵盖了大多数程序所需的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();
}

字符串数组和ArrayList被用于特定的指令。

以下是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();
}

我使用的输入文件大小为40KB。

这是结果 -

  • C ++代码运行时间为9秒。
  • C#代码:4秒!!!

哦,但这是在Linux上...使用C#在Mono上运行...而C++则使用g++。

好的,这是我在Windows上得到的结果 - Visual Studio 2003:

  • C#代码运行时间为9秒。
  • C++代码-令人震惊的370秒!!!

8
你在使用不同的数据结构和库代码,尽管"370秒"表明了一些可怕的情况——你不会在调试器中运行它吧? 我怀疑你使用的CSV库的性能比你使用的编程语言更有趣。 我会质疑在那种情况下使用向量及你所使用的优化方法。 另外,众所周知,在至少某些常见实现中,iostreams(特别是"myfile << *j << ", ";")写入文件的速度比其他方法要慢得多。 - Arafangion
6
最后,你在 C++ 版本中做了更多的工作。(为什么要清空 csvColumn、csvElement 和 csvLines?) - Arafangion
3
while循环的每次迭代都会销毁并重建std::istream、std::vector和std::string。由于while循环的主体在每次迭代后超出范围,因此所有在while范围内的变量都将在每次迭代中被销毁并重新构造。 - doug65536
2
从你的 C++ 代码看来,你正在尝试将一个文件复制到另一个文件。与其使用文件流、字符串、向量和字符串流之间的复杂交互,你可以直接将输入文件流复制到输出文件流中。这样做可以节省大量时间和内存。 - Zachary Kraus
3
要进行速度测试,请在内存中测试,不要涉及磁盘IO,除非您正在测试最新的SSD并且它专门用于您的性能应用程序。由于计算机不断向磁盘写入数据,即使您不触摸键盘也是如此。 - Peter
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接