在听StackOverflow播客的时候,经常有人说“真正的程序员”是用C语言编写的,而C语言的速度要快得多,因为它“接近机器”。把前面的断言留到另一篇文章,C有什么特别之处,使它比其他语言更快?或者换句话说:什么能阻止其他语言编译成二进制代码,使其运行速度与C语言一样快?


当前回答

不要轻信别人的话,看看在代码的任何性能关键部分,C语言和你选择的语言的反汇编。我认为你可以在Visual Studio运行时的反汇编窗口中看到已分解的. net。如果Java使用windbg有点棘手,应该是可能的,尽管如果你用。net来做,许多问题将是相同的。

如果没有必要的话,我不喜欢用C来编写,但我认为,这些回答中吹捧除C之外其他语言的速度的许多主张可以放在一边,只需用C和您选择的高级语言分解相同的例程,特别是如果涉及大量数据(这在性能关键型应用程序中很常见)。Fortran在其专业领域可能是个例外,不知道。它比C高吗?

第一次比较JITed代码和本地代码时,我解决了。net代码是否能与C代码运行得相当的所有问题。额外的抽象层次和所有的安全检查都带来了巨大的成本。同样的成本可能也适用于Java,但不要相信我的话,在性能至关重要的地方尝试一下。(有没有人足够了解JITed Java来在内存中找到一个编译过的过程?这当然是可能的)

其他回答

令人惊讶的是,“C/ c++必须比Java快,因为Java是解释性的”的神话仍然活跃。有几年前的文章,也有最近的文章,用概念或测量来解释为什么这种情况并不总是如此。

当前的虚拟机实现(顺便说一下,不仅仅是JVM)可以利用程序执行期间收集的信息来动态地优化代码,使用各种技术:

将频繁的方法呈现给机器代码, 内联小方法, 锁紧调整

以及各种其他调整,这些调整是基于了解代码实际在做什么,以及它运行的环境的实际特征。

里面有很多问题——大部分是我没有资格回答的问题。但对于最后一个:

有什么能阻止其他语言编译成运行速度和C一样快的二进制呢?

一句话,抽象。

C语言只比机器语言高出一到两个抽象层次。Java和. net语言距离汇编程序至少有3个抽象级别。Python和Ruby我不太确定。

通常,程序员的玩具越多(复杂的数据类型等),你离机器语言的距离就越远,需要做的翻译就越多。

我在这里和那里都偏离了,但这是基本的要点。

更新-------这篇文章有一些很好的评论,有更多的细节。

只需在您的IDE中逐步检查机器代码,您就会看到为什么它更快(如果它更快的话)。它省去了很多手把手的环节。很有可能你的Cxx也会被告知不要使用,在这种情况下,它应该是相同的。

编译器优化被高估了,就像几乎所有关于语言速度的看法一样。

优化生成的代码只会对热点代码产生影响,也就是说,没有函数调用(显式或隐式)的紧凑算法。在其他地方,收效甚微。

如果你花了一个月的时间用C语言构建的程序只需要0.05秒,而我花了一天的时间用Java写同样的程序,只需要0.10秒,那么C语言真的更快吗?

但是回答你的问题,编写良好的C代码通常会比其他语言编写的代码运行得更快,因为编写良好的C代码的一部分包括在接近机器的级别上进行手动优化。

尽管编译器确实非常聪明,但它们还不能创造性地提出与手工按摩算法竞争的代码(假设“手”属于一个优秀的C程序员)。

编辑:

很多评论都是这样的:“我用C语言编写,我不考虑优化。”

举个具体的例子:

在Delphi中我可以这样写:

function RemoveAllAFromB(a, b: string): string;
var
  before, after :string;
begin
  Result := b;
  if 0 < Pos(a,b) then begin
    before := Copy(b,1,Pos(a,b)-Length(a));
    after := Copy(b,Pos(a,b)+Length(a),Length(b));
    Result := before + after;
    Result := RemoveAllAFromB(a,Result);  //recursive
  end;
end;

用C语言写:

char *s1, *s2, *result; /* original strings and the result string */
int len1, len2; /* lengths of the strings */
for (i = 0; i < len1; i++) {
   for (j = 0; j < len2; j++) {
     if (s1[i] == s2[j]) {
       break;
     }
   }
   if (j == len2) {  /* s1[i] is not found in s2 */
     *result = s1[i]; 
     result++; /* assuming your result array is long enough */
   }
}

但是C版本中有多少优化呢?我们在实现方面做了很多我在Delphi版本中没有考虑到的决定。字符串是如何实现的?在特尔斐我看不出来。在C语言中,我已经决定它将是一个指向ASCII整数数组的指针,我们称之为字符。在C语言中,我们每次测试一个字符的存在性。在Delphi中,我使用Pos。

这只是一个小例子。在一个大型程序中,C程序员必须对每几行代码做出这类低级决策。它加起来就是一个手工制作、手工优化的可执行文件。

与其说C的速度快,不如说C的成本模型是透明的。如果一个C程序慢,它的慢是通过一个明显的方式:执行很多语句。与C语言中操作的代价相比,对对象(特别是反射)或字符串的高级操作可能具有不明显的代价。

标准ML(使用MLton编译器)和Objective Caml这两种语言通常编译成二进制文件的速度与C语言一样快。如果你检查一下基准测试游戏,你会发现对于一些基准测试,比如二叉树,OCaml版本比c更快(我没有找到任何MLton的条目)。但不要把枪战看得太严重;正如它所说的,它是一个游戏,结果通常反映了人们在调优代码上投入了多少精力。