Rust 比 C 更快吗?

yumo6662周前 (07-02)技术文章14

最近 Reddit 上有人在提问:

在其他条件相同的情况下,什么方法会让 Rust 实现比 C 实现更快?

我觉得这个问题很好,也很有趣!这个问题其实很难回答,因为它最终取决于“万物皆同”的具体含义。

我觉得这也使得语言之间的比较变得困难。可以通过以下几种方式来论证事物“相同”和“不同”,以及它们对运行时性能的影响。

内联汇编

Rust 语言内置了内联汇编。而 C 语言则将内联汇编作为一种非常常见的编译器扩展,以至于说它不是该语言的一部分都是一种有争议的吹毛求疵。

来看 Rust 语言中的一个代码示例:

以下是一个函数rdtsc用来读取时间戳,并返回其值。以下是 C 语言的代码实现示例:

#include <stdint.h>

uint64_t rdtsc(void)
{
    uint32_t lo, hi;
    __asm__ __volatile__ (
        "rdtsc"
        : "=a"(lo), "=d"(hi)
    );
    return ((uint64_t)hi << 32) | lo;
}

以下是在 rustc1.87.0和 clang下20.1.0相同功能的程序:

rdtsc:
        rdtsc
        shl     rdx, 32
        mov     eax, eax
        or      rax, rdx
        ret

以下是在线编译网站 Godbolt 上的链接:

https://godbolt.org/z/f7K8cfnx7

这算吗?我不知道。我觉得这跟问题本身没太大关系,但至少是回答问题的一种方式。

类似的代码,不同的结果

Rust 和 C 语言对于类似的代码可以有不同的语义。以下是 Rust 中的一个结构体:

struct Rust {
    x: u32,
    y: u64,
    z: u32,

这是 C 语言中的“相同”结构:

struct C {
    uint32_t x;
    uint64_t y;
    uint32_t z;
};

在 Rust 中,这个结构是 16 个字节(同样在 x86_64 上),而在 C 中,它是 24 个字节。这是由于 Rust 可以自由地重新排序字段以优化大小,而 C 语言则不能。

社会因素

有些人报告说,由于 Rust 的安全检查机制,他们更愿意编写比同等 C(或 C++)更“危险”的代码,因为在 C(或 C++)中,他们会进行更多复制以确保代码更安全。从同一个项目中的相同开发人员的角度来看,这似乎是“相同的”,但由于判断调用,代码会有所不同。

很久以前有一个示例是 Stylo 项目。Mozilla 曾两次尝试用 C++ 并行化 Firefox 浏览器的样式布局,但两次都失败了。因为多线程处理太棘手,难以实现。第三次,他们使用了 Rust,并成功交付。

这是同一个项目(虽然我认为不是同一个程序员),由同一个组织开发,但一次可行,一次则不行。

类似的问题也适用:假设我们有一个初级开发人员,他同时编写 Rust 和 C 语言来完成同一个任务。我们能否用其中一种语言写出更快的代码呢?这个问题取决于他的能力水平,但与编写同一份代码无关。这“一样”吗?我不知道。如果同一个任务交给两种语言的专家,一个非常精通 Rust 但不了解 C 语言的人,反之亦然,会怎么样呢?这个与初级开发人员或“普通”开发人员有什么区别?

编译时与运行时?

另一位 Reddit 用户在问题底部追问道:

我不是 Rust 专家,但大多数(所有?)安全检查不是都是编译时检查吗?它们应该不会对运行时产生任何影响。

这也是好问题!这部分是默认设置不同的另一个例子。

比如,array[0]的这种声明在两种语言中均有效。

Rust 语言在运行时会进行边界检查。而 C 语言则没有这种能力。在 Rust 中,我可以写array.get_unchecked(0),并获得 C 的语义。在 C 语言中,我需要编写边界检查来获得 Rust 的语义。

在 Rust 中,如果编译器能够证明它是安全的,那么该检查可能会被优化掉。在 C 语言中,如果我们手写边界检查,如果编译器能够证明它是安全的,那么该检查也可能被优化掉。

Rust 的许多安全检查是在编译时进行的,但也有一些工作是在运行时进行的。但这又引出了另一个有趣的问题:编译时检查可能会导致你为同一任务编写与 C 语言不同的代码。

一个常见的例子是使用索引而不是指针,这意味着生成的代码执行方式的不同。这种检查真的“在编译时”进行吗?从技术层面,在微观层面,是这样的。但在工程层面可能并非如此!

结论

我认为这个问题最重要的部分与所谓的可能性有关,即:

  1. 如果我们假设 C 是“最快的语言”,无论这意味着什么;
  2. Rust 不能做同样的事情,是否存在内部原因?

我认为答案是“否”,即使忽略内联汇编的情况也是如此。所以在这个最重要的、最根本的层面上,答案是“两者之间没有区别”。

但我们通常不会谈论这些。我们通常会在工程的背景下讨论某个事情,比如一个特定的项目,有特定的开发人员,有特定的时间限制等等。我认为这里变量太多,很难得出普遍的结论。

原文:

https://steveklabnik.com/writing/is-rust-faster-than-c

相关文章

C语言之编译器集合

C语言有多种不同的编译器,以下是常见的编译工具及其特点:一、主流C语言编译器1. GCC(GNU Compiler Collection)特点:开源、跨平台,支持多种语言(C、C++、Fortran...

C语言编译器,你用过哪种?

说到C语言,我想无论是从事IT行业的程序员也好,还是非专业人士也罢,对它都是有所耳闻的。C语言是一门历史很长的编程语言,其编译器和开发工具也多种多样,今天小编就为大家盘点那些我们可能使用过的C语言编辑...

推荐10个好用的C++在线编译器,去网吧学习不用配置环境了

很多时候我们会去网吧学习C++(不是),安装VS、Eclipse这样的大型软件没必要,但是下载vscode、mingw、cmake来配置环境比较麻烦,这时一个实用的C++在线编译器就非常难得和可贵了,...

C语言编译器标准

C语言编译器标准C语言的编译器标准由国际标准化组织(ISO)和国际电工委员会(IEC)共同制定,以下是主要版本的演进及特性:核心标准版本K&R C (1978)非正式标准,由 Brian Kernig...

哪款C语言编译器(IDE)适合初学者?

这里我们把“编译器”和“IDE(集成开发环境)”当做一个概念,不再加以区分。C语言的集成开发环境有很多种,尤其是 Windows 下,多如牛毛,初学者往往不知道该如何选择,本节我们就针对 Window...

初学者选择哪一款编译器比较好?

工欲善其事必先利其器,工作了这些年用的工具着时不少,一步步走过来也算是蹒跚满志。现如今只剩下会用vim gcc了。不是其它工具不会用因为用的少了慢慢的就生疏了,习惯形成了也就不好改了。要我说用那款编译...