还是现在反过来了?
据我所知,c#在某些领域被证明比c++更快,但我从来没有勇气亲自测试它。
我想你们任何人都可以详细解释这些差异,或者告诉我有关信息的正确位置。
还是现在反过来了?
据我所知,c#在某些领域被证明比c++更快,但我从来没有勇气亲自测试它。
我想你们任何人都可以详细解释这些差异,或者告诉我有关信息的正确位置。
当前回答
C/ c++在有大型数组或数组(任何大小)上的大量循环/迭代的程序中可以表现得更好。这就是为什么在C/ c++中图形化通常要快得多,因为几乎所有的图形化操作都基于繁重的数组操作。net在数组索引操作中是出了名的慢,这是由于所有的安全检查,这对于多维数组尤其如此(是的,矩形c#数组甚至比锯齿形c#数组还要慢)。
The bonuses of C/C++ are most pronounced if you stick directly with pointers and avoid Boost, std::vector and other high-level containers, as well as inline every small function possible. Use old-school arrays whenever possible. Yes, you will need more lines of code to accomplish the same thing you did in Java or C# as you avoid high-level containers. If you need a dynamically sized array, you will just need to remember to pair your new T[] with a corresponding delete[] statement (or use std::unique_ptr)—the price for the extra speed is that you must code more carefully. But in exchange, you get to rid yourself of the overhead of managed memory / garbage collector, which can easily be 20% or more of the execution time of heavily object-oriented programs in both Java and .NET, as well as those massive managed memory array indexing costs. C++ apps can also benefit from some nifty compiler switches in certain specific cases.
I am an expert programmer in C, C++, Java, and C#. I recently had the rare occasion to implement the exact same algorithmic program in the latter 3 languages. The program had a lot of math and multi-dimensional array operations. I heavily optimized this in all 3 languages. The results were typical of what I normally see in less rigorous comparisons: Java was about 1.3x faster than C# (most JVMs are more optimized than the CLR), and the C++ raw pointer version came in about 2.1x faster than C#. Note that the C# program only used safe code—it is my opinion that you might as well code it in C++ before using the unsafe keyword.
Lest anyone think I have something against C#, I will close by saying that C# is probably my favorite language. It is the most logical, intuitive and rapid development language I've encountered so far. I do all my prototyping in C#. The C# language has many small, subtle advantages over Java (yes, I know Microsoft had the chance to fix many of Java's shortcomings by entering the game late and arguably copying Java). Toast to Java's Calendar class anyone? If Microsoft ever spends real effort to optimize the CLR and the .NET JITter, C# could seriously take over. I'm honestly surprised they haven't already—they did so many things right in the C# language, why not follow it up with heavy-hitting compiler optimizations? Maybe if we all beg.
其他回答
c++(或C)为您提供了对数据结构的细粒度控制。如果你想玩,你有这个选择。大型托管Java或。net应用程序(OWB, Visual Studio 2005),它们使用Java/。NET库自带包袱。我曾见过OWB设计会话使用超过400 MB的RAM,立方体或ETL设计的bid也达到100 MB。
在可预测的工作负载上(例如重复一个过程多次的大多数基准测试),JIT可以为您提供优化得足够好的代码,没有实际差别。
在大型应用程序上,差异与其说是JIT,不如说是代码本身使用的数据结构。当应用程序的内存很重时,您将获得较低的缓存使用效率。在现代cpu上,缓存丢失是非常昂贵的。C或c++的真正优势在于,您可以优化数据结构的使用,从而更好地使用CPU缓存。
没有严格的理由说明为什么基于字节码的语言(如c#或Java)不能像c++代码一样快。然而,c++代码在很长一段时间内都要快得多,今天在许多情况下仍然如此。这主要是因为更高级的JIT优化实现起来比较复杂,而真正酷的JIT优化现在才出现。
所以在很多情况下,c++更快。但这只是答案的一部分。c++实际上更快的情况是高度优化的程序,其中专业程序员彻底优化了代码。这不仅非常耗时(因此非常昂贵),而且由于过度优化通常会导致错误。
On the other hand, code in interpreted languages gets faster in later versions of the runtime (.NET CLR or Java VM), without you doing anything. And there are a lot of useful optimizations JIT compilers can do that are simply impossible in languages with pointers. Also, some argue that garbage collection should generally be as fast or faster as manual memory management, and in many cases it is. You can generally implement and achieve all of this in C++ or C, but it's going to be much more complicated and error prone.
As Donald Knuth said, "premature optimization is the root of all evil". If you really know for sure that your application will mostly consist of very performance critical arithmetic, and that it will be the bottleneck, and it's certainly going to be faster in C++, and you're sure that C++ won't conflict with your other requirements, go for C++. In any other case, concentrate on first implementing your application correctly in whatever language suits you best, then find performance bottlenecks if it runs too slow, and then think about how to optimize the code. In the worst case, you might need to call out to C code through a foreign function interface, so you'll still have the ability to write critical parts in lower level language.
请记住,优化一个正确的程序相对容易,但更正一个优化的程序要难得多。
给出实际的速度优势百分比是不可能的,这在很大程度上取决于你的代码。在许多情况下,编程语言实现甚至不是瓶颈。请带着极大的怀疑态度使用http://benchmarksgame.alioth.debian.org/上的基准测试,因为这些测试的主要是算术代码,很可能与您的代码完全不同。
首先,我不同意这个问题的部分公认答案(并且得到了好评),我说:
为什么jit代码比适当优化的c++(或其他没有运行时开销的语言)运行得慢,实际上有很多原因。 程序包括:
根据定义,在运行时用于jit代码的计算周期在程序执行中不可用。 JITter中的任何热路径都将与你的代码竞争指令和CPU中的数据缓存。我们知道缓存在性能方面占主导地位,而像c++这样的原生语言在设计上并没有这种类型的争用。 运行时优化器的时间预算必然比编译时优化器的时间预算更有限(正如另一个评论者指出的那样)。
底线:最终,您几乎肯定能够在c++中创建比在c#中更快的实现。
现在,说了这么多,速度到底有多快是无法量化的,因为有太多的变量:任务、问题领域、硬件、实现质量和许多其他因素。您将在您的场景上运行测试,以确定性能上的差异,然后决定是否值得额外的努力和复杂性。
这是一个很长很复杂的话题,但为了完整起见,我觉得值得一提的是,c#的运行时优化器非常出色,能够在运行时执行某些c++编译时(静态)优化器无法实现的动态优化。即便如此,优势仍然主要体现在本机应用程序方面,但动态优化器是上面给出的“几乎肯定”限定符的原因。
--
在相对性能方面,我也被我在其他一些答案中看到的数字和讨论所困扰,所以我想我应该插话,同时为我上面所做的陈述提供一些支持。
这些基准测试的很大一部分问题是,你不能像写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#: 289毫秒,c++ 152毫秒(大约快90%)
观察
Changing the C# implementation to the same 1d array implementation yielded Init: 40ms, Fill: 171ms, Total: 211ms (C++ was still almost 40% faster). It is much harder to design and write "fast" code in C++ than it is to write "regular" code in either language. It's (perhaps) astonishingly easy to get poor performance in C++; we saw that with unreserved vectors performance. And there are lots of pitfalls like this. C#'s performance is rather amazing when you consider all that is going on at runtime. And that performance is comparatively easy to access. More anecdotal data comparing the performance of C++ and C#: https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=gpp&lang2=csharpcore
归根结底,c++为您提供了对性能的更多控制。你想用指针吗?一个参考吗?栈内存?堆吗?动态多态还是用静态多态(通过模板/CRTP)消除虚表的运行时开销?在c++中你必须…呃,自己做出所有这些选择(甚至更多),理想情况下,这样你的解决方案才能最好地解决你正在处理的问题。
问问自己是否真的想要或需要该控件,因为即使对于上面的简单示例,您也可以看到尽管性能有了显著的改进,但它需要更深入的投资才能访问。
这要看情况。如果字节码被转换成机器代码(不仅仅是JIT)(我的意思是如果你执行程序),如果你的程序使用了很多分配/释放,它可能会更快,因为GC算法只需要一次(理论上)通过整个内存,但正常的malloc/realloc/free C/ c++调用会在每次调用上引起开销(调用开销、数据结构开销、缓存丢失;))。
所以这在理论上是可能的(对于其他GC语言也是如此)。
我并不认为不能在大多数应用程序中使用c#元编程有什么极端的缺点,因为大多数程序员都不使用它。
另一个很大的优势是SQL,像LINQ“扩展”一样,为编译器提供了优化数据库调用的机会(换句话说,编译器可以将整个LINQ编译为一个“blob”二进制文件,其中调用的函数内联或为您的使用优化,但我只是在这里推测)。
这实际上取决于你想在代码中实现什么。我听说这只是一个都市传说,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;
}