是C#真的慢于说C ++? [英] Is C# really slower than say C++?

查看:114
本文介绍了是C#真的慢于说C ++?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在想,现在这个问题一段时间。

I've been wondering about this issue for a while now.

当然,有些事情在C#中未对速度进行了优化,因此,使用这些对象或语言的调整(如LINQ)可能会导致code要慢一些。

Of course there are things in C# that aren't optimized for speed, so using those objects or language tweaks (like LinQ) may cause the code to be slower.

但是,如果你不使用任何的调整,但只是比较code在C#和C同一块++(这很容易翻译一个到另一个)。它真的是很慢?

But if you don't use any of those tweaks, but just compare the same pieces of code in C# and C++ (It's easy to translate one to another). Will it really be that much slower ?

我见过的比较中显示,C#可能会在某些情况下甚至更快,因为在理论上的JIT编译器应该优化实时code和获得更好的结果:

I've seen comparisons that show that C# might be even faster in some cases, because in theory the JIT compiler should optimize the code in real time and get better results:

托管或非托管?

我们应该记住,JIT编译器编译实时的code,但是这是一个1时开销,同样code(一度达到并编译)并不需要在运行再次编译时间。

We should remember that the JIT compiler compiles the code at real time, but that's a 1-time overhead, the same code (once reached and compiled) doesn't need to be compiled again at run time.

GC没有增添了不少开销,要么,除非你创建和销毁数以千计的物体(如使用字符串,而不是StringBuilder的)。而这样做,在C ++中也将是昂贵的。

The GC doesn't add a lot of overhead either, unless you create and destroy thousands of objects (like using String instead of StringBuilder). And doing that in C++ would also be costly.

这是我想提出的另一点是在.net中的DLL推出之间的更好的沟通。在.NET平台比通信管理的基于COM的DLL好得多。

Another point that I want to bring up is the better communication between DLLs introduced in .Net. The .Net platform communicates much better than Managed COM based DLLs.

我看不出有任何内在原因,语言要慢,而且我真的不认为C#是比C ++(无论是从经验和缺乏一个很好的解释)。

I don't see any inherent reason why the language should be slower, and I don't really think that C# is slower than C++ (both from experience and lack of a good explanation)..

那么,将一块写在C#一样code会比用C同code ++慢?结果
在如果是这样的话,为什么?

So, will a piece of the same code written in C# will be slower than the same code in C++ ?
In if so, then WHY ?

其他的一些引用(谈论了一下,但没有为什么的解释):

Some other reference (Which talk about that a bit, but with no explanation about WHY):

<一个href=\"http://stackoverflow.com/questions/787375/why-would-you-want-to-use-c-if-its-slower-than-c\">Why你会想,如果使用C#的速度慢于C ++?

推荐答案

警告:你问的问题实在是pretty复杂 - 也许远远超过了你认识。其结果是,这是一个的真正的长期答案。

Warning: The question you've asked is really pretty complex -- probably much more so than you realize. As a result, this is a really long answer.

从纯理论的角度来看,有可能是一个简单的答案是:有(可能)关于C#,真正prevents它被尽可能快地C ++什么。尽管理论,然而,也有一些实际的原因,它的的在某些情况下一些事情更慢。

From a purely theoretical viewpoint, there's probably a simple answer to this: there's (probably) nothing about C# that truly prevents it from being as fast as C++. Despite the theory, however, there are some practical reasons that it is slower at some things under some circumstances.

我会考虑的差异三个基本方面:语言功能,虚拟机执行,和垃圾收集。后两人经常一起去,但也可以是独立的,所以我会看他们分开。

I'll consider three basic areas of differences: language features, virtual machine execution, and garbage collection. The latter two often go together, but can be independent, so I'll look at them separately.

C ++放在模板强调了大量的,并且在模板系统的功能,在很大程度上是旨在允许尽可能在编译时完成,所以从程序的角度看,它们是静态的。 模板元编程完全可以任意计算在编译时进行(即模板系统是图灵完备)。因此,基本上不依赖于来自用户的输入的任何可以在编译时被计算,所以在运行时它是一个简单的恒定。输入这个可以,但是,包括像类型的信息,所以你会在C#中运行时通过反射做了很大的通常是在编译时通过模板元编程用C ++做。肯定是有运行速度和多功能性之间进行权衡,虽然 - 什么模板可以做的,他们做静态的,但他们根本无法做一切能反射

C++ places a great deal of emphasis on templates, and features in the template system that are largely intended to allow as much as possible to be done at compile time, so from the viewpoint of the program, they're "static." Template meta-programming allows completely arbitrary computations to be carried out at compile time (I.e., the template system is Turing complete). As such, essentially anything that doesn't depend on input from the user can be computed at compile time, so at runtime it's simply a constant. Input to this can, however, include things like type information, so a great deal of what you'd do via reflection at runtime in C# is normally done at compile time via template metaprogramming in C++. There is definitely a trade-off between runtime speed and versatility though -- what templates can do, they do statically, but they simply can't do everything reflection can.

在语言特征的差异意味着,在由音译一些C#为C简单地比较这两种语言几乎任何企图++(反之亦然),很可能在某个地方毫无意义的,误导性(和相同的产生的结果将是其他大多数真语言对以及)。一个简单的事实是,任何超过code左右的几行大,几乎没有人在所有可能使用的语言以同样的方式(或足够接近以同样的方式),这样的对比告诉你任何东西这些语言在现实生活中是如何工作的。

The differences in language features mean that almost any attempt at comparing the two languages simply by transliterating some C# into C++ (or vice versa) is likely to produce results somewhere between meaningless and misleading (and the same would be true for most other pairs of languages as well). The simple fact is that for anything larger than a couple lines of code or so, almost nobody is at all likely to use the languages the same way (or close enough to the same way) that such a comparison tells you anything about how those languages work in real life.

像几乎任何合理的现代虚拟机,微软对.NET可以和会做JIT(又名动态)编写。这将重新presents一些权衡虽然。首先,几乎每个VM(包括微软的,我相信)试图做出什么来编译和如何跨preT明智的决定。它通过跨preting的code它遇到的第几次做到这一点。它分析它是如何往往是跨preting特别code,当它超过一定阈值时,数字是的可能的执行够多了,这是值得编译它获得的执行速度。这有一个明显的问题:过一段时间,就可以猜错了 - 你有很多code的一个执行的只是的往往不足以引发编译,但永远不会被再次使用,你'再失去pretty严重:几乎所有的执行是通过缓慢,除preTED路径,然后你支付编译的价格,但你没有从编译受益。凭心而论,我要补充一点,这是正常的code pretty不寻常的,但如果你真的希望的到,它通常是pretty容易引发它。

Like almost any reasonably modern VM, Microsoft's for .NET can and will do JIT (aka "dynamic") compilation. This represents a number of trade-offs though. First, almost every VM (including Microsoft's, I believe) attempts to make intelligent decisions about what to compile and what to interpret. It does this by interpreting the code the first few times it's encountered. It profiles how often it's interpreting particular code, and when it exceeds a certain threshold, figures it's likely to execute enough more that it's worth compiling it to gain execution speed. This has an obvious problem: once in a while, it can guess wrong -- you have a lot of code that executes just often enough to trigger compilation, but then never gets used again, you're losing pretty badly: nearly all your execution is via the slow, interpreted path, then you pay the price of compilation, but then you get no benefit from the compilation. In fairness, I should add that this is pretty unusual in normal code, but if you actually want to, it's usually pretty easy to trigger it.

二,优化code(像大多数其他优化问题)在很大程度上是一个NP完全问题。任何东西,但真正的琐碎/玩具程序,你是pretty几乎保证你不会真正的优化的结果(即,你不会找到真正的最优) - 优化只会使$ C $ç的更好的比它是previously。这是公知的相当多的优化,然而,需要的时间显着量(与通常,存储器)来执行。随着JIT编译器,而编译器运行用户在等待。尤其是当与第一个问题(导出从编译很少或没有益处的可能性)耦合,大多数的更昂贵的优化技术排除。静态编译有两个好处:首先,如果是缓慢的(例如,建立一个大的系统),它通常在服务器上进行的,而的时间花费在等待它。第二,可以生成一个可执行的一旦的,并且被许多人使用的许多倍。第一最小化优化的成本;第二摊销小得多的成本比处决一个更大的数字。

Second, optimizing code (like most other optimization problems) is largely an NP-complete problem. For anything but a truly trivial/toy program, you're pretty nearly guaranteed you won't truly "optimize" the result (i.e., you won't find the true optimum) -- the optimizer will simply make the code better than it was previously. Quite a few optimizations that are well known, however, take a substantial amount of time (and, often, memory) to execute. With a JIT compiler, the user is waiting while the compiler runs. Especially when coupled with the first problem (possibility of deriving little or no benefit from compilation), most of the more expensive optimization techniques are ruled out. Static compilation has two advantages: first of all, if it's slow (e.g., building a large system) it's typically carried out on a server, and nobody spends time waiting for it. Second, an executable can be generated once, and used many times by many people. The first minimizes the cost of optimization; the second amortizes the much smaller cost over a much larger number of executions.

由于在原来的问题(和许多其他网站)提到的JIT编译确实有目标环境,这应该(至少在理论上)抵消这种优势的认识的可能性。毫无疑问,这一因素也抵消静态编译的缺点至少一部分。对于少数,而特定类型code和目标环境中,它的可以的甚至超过静态编译的优势。至少在我的测试和经验,但是,这是相当不寻常的。目标取决于优化大多似乎要么使相当小的差异,或者只能应用于(自动,反正),以十分具体的问题。

As mentioned in the original question (and many other web sites) JIT compilation does have the possibility of greater awareness of the target environment, which should (at least theoretically) offset this advantage. There's no question that this factor does offset at least part of the disadvantage of static compilation. For a few rather specific types of code and target environments, it can even outweigh the advantages of static compilation. At least in my testing and experience, however, this is fairly unusual. Target dependent optimizations mostly seem to either make fairly small differences, or can only be applied (automatically, anyway) to fairly specific types of problems.

使用VM还具有提高高速缓冲存储器的使用情况的可能性。指示为VM常常比本机机器指令更紧凑。更绝的是可以放入高速缓存一定量的,所以你站在任何给定的code在需要时缓存是一个更好的机会。这可以帮助保持VM code国米preTED执行更具竞争力(在速度方面)比大多数人最初会想到 - 你可以执行的很多的的现代CPU上的说明由所花费的时间的有一个的缓存未命中。

Using a VM also has a possibility of improving cache usage. Instructions for a VM are often more compact than native machine instructions. More of them can fit into a given amount of cache memory, so you stand a better chance of any given code being in cache when needed. This can help keep interpreted execution of VM code more competitive (in terms of speed) than most people would initially expect -- you can execute a lot of instructions on a modern CPU in the time taken by one cache miss.

另外值得一提的是,这个因素是不是的不一定的两个根本不同的。没有什么preventing(例如)从生产打算在虚拟机上运行的输出(有或无JIT)C ++编译器。事实上,微软的C ++ / CLI是的的是 - 一个(几乎)符合C ++编译器(虽然,有很多一致的扩展)产生打算在虚拟机上运行的输出。相反大概也是如此:在理论产生的天然code应该是可能的,以及一个C#编译器

It's also worth mentioning that this factor isn't necessarily different between the two at all. There's nothing preventing (for example) a C++ compiler from producing output intended to run on a virtual machine (with or without JIT). In fact, Microsoft's C++/CLI is nearly that -- an (almost) conforming C++ compiler (albeit, with a lot of conforming extensions) that produces output intended to run on a virtual machine. The reverse is probably also true: in theory a C# compiler that produced native code should be possible as well.

这是我所看到的,我会说垃圾收集是最穷的理解这三个因素。只是一个很明显的例子,问题在这里提到:GC不添加大量的开销或者,除非你创建和销毁成千上万个对象[...]。在现实中,如果你创建的的摧毁成千上万个对象,从垃圾收集的开销一般会相当低。 .NET使用世代清道夫,它是各种复制收藏家。垃圾收集器的工作原理是从地方(例如,寄存器和执行栈)的指针/引用开始的的可访问。然后,它追逐的指针已在堆中分配的对象。它探讨了进一步的指针/引用这些对象,直到它一直遵循所有的人对任何链的末端​​,并找到了所有(至少潜在的)访问的对象。在使用于下一步骤,它需要所有属于对象(或至少<青霉>可能是的),并在存储器的一端是通过复制它们全部成一个连续的块压缩堆在堆管理。内存的其余部分则是免费的(不必运行模终结,但至少在精心编写的code,它们也非常难得,我会忽略他们的时刻)。

From what I've seen, I'd say garbage collection is the poorest-understood of these three factors. Just for an obvious example, the question here mentions: "GC doesn't add a lot of overhead either, unless you create and destroy thousands of objects [...]". In reality, if you create and destroy thousands of objects, the overhead from garbage collection will generally be fairly low. .NET uses a generational scavenger, which is a variety of copying collector. The garbage collector works by starting from "places" (e.g., registers and execution stack) that pointers/references are known to be accessible. It then "chases" those pointers to objects that have been allocated on the heap. It examines those objects for further pointers/references, until it has followed all of them to the ends of any chains, and found all the objects that are (at least potentially) accessible. In the next step, it takes all of the objects that are (or at least might be) in use, and compacts the heap by copying all of them into a contiguous chunk at one end of the memory being managed in the heap. The rest of the memory is then free (modulo finalizers having to be run, but at least in well-written code, they're rare enough that I'll ignore them for the moment).

这意味着,如果你创建的和摧毁的大量的对象,垃圾收集增加了非常小的开销。由垃圾回收周期所花费的时间几乎完全依赖于已创建的对象的数量,但的的破坏。创建和匆忙销毁对象的主要后果很简单,就是GC有更频繁地运行,但每个周期依然会很快。如果你创建对象和的的摧毁它们,GC将运行更频繁的的每个周期会因为它花费更多的时间追逐指针潜在的,活动对象慢得多,的却是它仍然在使用更多的时间复制对象。

What this means is that if you create and destroy lots of objects, garbage collection adds very little overhead. The time taken by a garbage collection cycle depends almost entirely on the number of objects that have been created but not destroyed. The primary consequence of creating and destroying objects in a hurry is simply that the GC has to run more often, but each cycle will still be fast. If you create objects and don't destroy them, the GC will run more often and each cycle will be substantially slower as it spends more time chasing pointers to potentially-live objects, and it spends more time copying objects that are still in use.

要解决这个问题,代清除工作的假设,即有无的对象相当长一段时间仍然活着很可能会持续相当一段时间保持活着。在此基础上,它有一个系统,其中幸存下来的垃圾收集循环的一些数量的对象得到终身,而垃圾收集器开始简单地假设他们仍然在使用,所以不是每个周期复制它们,它只是叶子他们孤独。这是一个有效的假设往往不够,代清除通常比大多数其他形式的GC相当低的开销。

To combat this, generational scavenging works on the assumption that objects that have remained "alive" for quite a while are likely to continue remaining alive for quite a while longer. Based on this, it has a system where objects that survive some number of garbage collection cycles get "tenured", and the garbage collector starts to simply assume they're still in use, so instead of copying them at every cycle, it simply leaves them alone. This is a valid assumption often enough that generational scavenging typically has considerably lower overhead than most other forms of GC.

手动内存管理往往只是作为知之甚少。只是一个例子,在比较多种尝试假定所有的手动内存管理遵循一个特定的模式,以及(如最佳匹配分配​​)。这往往是很少(如果有的话),比许多人的有关垃圾回收的信念(例如,在wides $ P $垫假设它使用引用计数正常完成)。

"Manual" memory management is often just as poorly understood. Just for one example, many attempts at comparison assume that all manual memory management follows one specific model as well (e.g., best-fit allocation). This is often little (if any) closer to reality than many peoples' beliefs about garbage collection (e.g., the widespread assumption that it's normally done using reference counting).

由于各种各样的两个垃圾收集的的手动内存管理策略,这是相当困难的两个比较整体速度方面。尝试(本身)来分配和/或释放内存的速度相比是pretty几乎保证产生的结果充其量是毫无意义的,和赤裸裸的误导在最坏的情况。

Given the variety of strategies for both garbage collection and manual memory management, it's quite difficult to compare the two in terms of overall speed. Attempting to compare the speed of allocating and/or freeing memory (by itself) is pretty nearly guaranteed to produce results that are meaningless at best, and outright misleading at worst.

由于相当多的博客,网站,杂志文章等,声称提供客观的证据在一个方向或另一个方向,我会在我的两美分的价值在这个问题上也是如此。

Since quite a few blogs, web sites, magazine articles, etc., claim to provide "objective" evidence in one direction or another, I'll put in my two-cents worth on that subject as well.

大多数基准有点像少年决定比赛他们的汽车,并谁就赢得到保留两​​辆车。该网站虽然在一个关键方式不同:他们的家伙是谁发布的基准获得驾驶两辆车。通过一些奇怪的机会,他的车总是获胜,而其他人只能选择了相信我,我的真正的驾驶自己的车一样快,它会去。

Most of these benchmarks are a bit like teenagers deciding to race their cars, and whoever wins gets to keep both cars. The web sites differ in one crucial way though: they guy who's publishing the benchmark gets to drive both cars. By some strange chance, his car always wins, and everybody else has to settle for "trust me, I was really driving your car as fast as it would go."

这很容易写一个贫穷的基准产生意味着旁边没有结果。几乎任何人接近必要的设计,能产生什么有意义的基准技能在任何地方,也有技能,以生产一会给他希望他的决定的结果。事实上它可能的更容易的写code意图产生比code,将真正产生有意义的结果特定的结果。

It's easy to write a poor benchmark that produces results that mean next to nothing. Almost anybody with anywhere close to the skill necessary to design a benchmark that produces anything meaningful, also has the skill to produce one that will give the results he's decided he wants. In fact it's probably easier to write code intended to produce a specific result than code that will really produce meaningful results.

正如我的朋友詹姆斯·观世所说:不要相信你没有伪造自己的基准。

As my friend James Kanze put it, "never trust a benchmark you didn't falsify yourself."

有没有简单的答案。我相当肯定,我可以抛硬币并推出一对骰子挑选赢家和百分比,它会获胜,并写一个看似公平​​的基准,其中所选择的语言被选择的比例胜出。

There is no simple answer. I'm reasonably certain I could flip a coin and roll a pair of dice to pick a winner and percentage by which it would win, and write a seemingly fair benchmark in which the chosen language won by the chosen percentage.

正如其他人所指出的那样,为的的code,速度几乎是无关紧要的。推论到(这是更经常被忽略)是在小code其中速度非常重要,它通常是相当重要的很多的。至少在我的经验,为code它真正的问题呢,C ++几乎是永远的赢家。有肯定有利于C#的因素,但在实践中他们似乎被有利于C ++因素抵消。你当然可以找到基准,将显示您所选择的结果,但是当你编写真正code,几乎总是可以使其更快在C ++中比在C#中。它可能(也可能不)需要更多的技巧和/或努力写,但它几乎总是可能的。

As others have pointed out, for most code, speed is almost irrelevant. The corollary to that (which is much more often ignored) is that in the little code where speed does matter, it usually matters a lot. At least in my experience, for the code where it really does matter, C++ is almost always the winner. There are definitely factors that favor C#, but in practice they seem to be outweighed by factors that favor C++. You can certainly find benchmarks that will indicate the outcome of your choice, but when you write real code, you can almost always make it faster in C++ than in C#. It might (or might not) take more skill and/or effort to write, but it's virtually always possible.

这篇关于是C#真的慢于说C ++?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆