c# - 混合编程 - 为什么java比c慢




C++比C#快多少? (18)

或者现在是另一种方式?

从我听说的有一些地方C#证明比C ++更快,但我从来没有胆量来自己测试它。

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


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

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


C ++(或C就此而言)使您能够对数据结构进行细粒度的控制。 如果你想咬一口,你有这个选择。 大型托管的Java或.NET应用程序(OWB, Visual Studio 2005 )使用Java / .NET库的内部数据结构,随身携带行李。 我已经看到OWB设计者会话使用超过400 MB的RAM和BIDS,以进入100多MB的立方体或ETL设计。

在可预测的工作负载(例如大多数重复某个进程的基准测试)上,JIT可以为您提供足够优化的代码,使其没有实际区别。

国际海事组织在大型应用程序上的差别不在于代码本身使用的数据结构。 如果应用程序内存很大,则缓存使用效率会降低。 现代CPU上的高速缓存未命中相当昂贵。 在C或C ++真正获胜的地方,您可以优化数据结构的使用,以便与CPU缓存良好地协作。


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


> 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:

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!!!

It really depends on what you're trying to accomplish in your code. I've heard that it's just stuff of urban legend that there is any performance difference between VB.NET, C# and managed C++. However, I've found, at least in string comparisons, that managed C++ beats the pants off of C#, which in turn beats the pants off of VB.NET.

I've by no means done any exhaustive comparisons in algorithmic complexity between the languages. I'm also just using the default settings in each of the languages. In VB.NET I'm using settings to require declaration of variables, etc. Here is the code I'm using for managed C++: (As you can see, this code is quite simple). I'm running the same in the other languages in Visual Studio 2013 with .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;
}

一种特殊的情况是,C ++仍然占上风(并且在未来几年内)将会在编译时预先确定多态决策。

一般来说,封装和延迟决策是一件好事,因为它使代码更具动态性,更容易适应不断变化的需求并更容易用作框架。 这就是为什么C#中的面向对象编程非常富有成效,并且可以在术语“泛化”下进行概括。 不幸的是,这种特殊的泛化在运行时需要付出代价。

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

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


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


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

而当你接受其他许多人提到的所有其他编译时优化,以及缺乏安全性的时候,的确意味着更多的速度......

我认为C ++在原始速度和最小内存消耗方面是明显的选择。 但是这也意味着需要更多的时间来开发代码并确保您不会泄漏内存或导致任何空指针异常。

判决:

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

  • C ++:发展缓慢,运行速度更快。


它快五个橙子。 或者说:没有(正确的)一揽子答案。 C ++是一种静态编译的语言(但是后来还有配置文件引导优化),C#运行在JIT编译器的帮助下运行。 有很多不同之处,像“多快”这样的问题是无法回答的,甚至没有给出数量级的答案。


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

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


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


我将首先不同意这个问题的一部分接受的(并且是高效的)答案,并指出:

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

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

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

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

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

现在,就这么说,实际上无法量化的速度有多快 ,因为变量太多:任务,问题域,硬件,实施质量以及许多其他因素。 您将针对您的场景运行测试,以确定额外的努力和复杂性是否值得。

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

-

就相对表现而言,我还对其他答案中看到的数字和讨论感到不安,所以我认为我会在同一时间内为上述陈述提供一些支持。

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

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

1)使用了vector :: reserve()

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

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);
}

运行时间(Release):Init: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 ++让你对性能有更多的控制。 你想用指针吗? 参考? 堆栈内存? 堆? 动态多态或消除具有静态多态性的vtable的运行时间开销(通过模板/ CRTP)? 在C ++中,你必须......呃, 自己做出所有这些选择(更多),理想的是让你的解决方案最好地解决你正在处理的问题。

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


我已经在C ++和C#中测试了vector - List和简单的2d数组。

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

我使用的是Intel Core2Duo [email protected],C# - .NET 4.0。

我知道矢量实现不同于C#列表,但我只是想测试用来存储我的对象(以及能够使用索引存取器)的集合。

当然,你需要清除内存(假设每次使用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 ++

  • 600/606 ms阵列初始化,
  • 200/270毫秒阵列填充,
  • 1秒/ 13秒矢量初始化和填充。

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

C#:

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

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


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

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


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

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


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

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

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





benchmarking