最近Reddit上有人在提问:
我觉得这个问题很好,也很有趣!这个问题其实很难回答,因为它最终取决于“万物皆同”的具体含义。
我觉得这也使得语言之间的比较变得困难。可以通过以下几种方式来论证事物“相同”和“不同”,以及它们对运行时性能的影响。
内联汇编Rust语言内置了内联汇编。而C语言则将内联汇编作为一种非常常见的编译器扩展,以至于说它不是该语言的一部分都是一种有争议的吹毛求疵。
来看Rust语言中的一个代码示例:
以下是一个函数rdtsc用来读取时间戳,并返回其值。以下是C语言的代码实现示例:
#_trdtsc(void){uint32_tlo,hi;__asm____volatile__("rdtsc":"=a"(lo),"=d"(hi));return((uint64_t)hi32)|lo;}以下是在和clang下20.1.0相同功能的程序:
这算吗?我不知道。我觉得这跟问题本身没太大关系,但至少是回答问题的一种方式。
类似的代码,不同的结果Rust和C语言对于类似的代码可以有不同的语义。以下是Rust中的一个结构体:
structRust{x:u32,y:u64,z:u32,这是C语言中的“相同”结构:
structC{uint32_tx;uint64_ty;uint32_tz;};在Rust中,这个结构是16个字节(同样在x86_64上),而在C中,它是24个字节。这是由于Rust可以自由地重新排序字段以优化大小,而C语言则不能。
社会因素有些人报告说,由于Rust的安全检查机制,他们更愿意编写比同等C(或C++)更“危险”的代码,因为在C(或C++)中,他们会进行更多复制以确保代码更安全。从同一个项目中的相同开发人员的角度来看,这似乎是“相同的”,但由于判断调用,代码会有所不同。
很久以前有一个示例是Stylo项目。Mozilla曾两次尝试用C++并行化Firefox浏览器的样式布局,但两次都失败了。因为多线程处理太棘手,难以实现。第三次,他们使用了Rust,并成功交付。
这是同一个项目(虽然我认为不是同一个程序员),由同一个组织开发,但一次可行,一次则不行。
类似的问题也适用:假设我们有一个初级开发人员,他同时编写Rust和C语言来完成同一个任务。我们能否用其中一种语言写出更快的代码呢?这个问题取决于他的能力水平,但与编写同一份代码无关。这“一样”吗?我不知道。如果同一个任务交给两种语言的专家,一个非常精通Rust但不了解C语言的人,反之亦然,会怎么样呢?这个与初级开发人员或“普通”开发人员有什么区别?
编译时与运行时?另一位Reddit用户在问题底部追问道:
这也是好问题!这部分是默认设置不同的另一个例子。
Rust语言在运行时会进行边界检查。而C语言则没有这种能力。在Rust中,我可以写_unchecked(0),并获得C的语义。在C语言中,我需要编写边界检查来获得Rust的语义。
在Rust中,如果编译器能够证明它是安全的,那么该检查可能会被优化掉。在C语言中,如果我们手写边界检查,如果编译器能够证明它是安全的,那么该检查也可能被优化掉。
Rust的许多安全检查是在编译时进行的,但也有一些工作是在运行时进行的。但这又引出了另一个有趣的问题:编译时检查可能会导致你为同一任务编写与C语言不同的代码。
一个常见的例子是使用索引而不是指针,这意味着生成的代码执行方式的不同。这种检查真的“在编译时”进行吗?从技术层面,在微观层面,是这样的。但在工程层面可能并非如此!
结论我认为这个问题最重要的部分与所谓的可能性有关,即:
如果我们假设C是“最快的语言”,无论这意味着什么;
Rust不能做同样的事情,是否存在内部原因?
我认为答案是“否”,即使忽略内联汇编的情况也是如此。所以在这个最重要的、最根本的层面上,答案是“两者之间没有区别”。
但我们通常不会谈论这些。我们通常会在工程的背景下讨论某个事情,比如一个特定的项目,有特定的开发人员,有特定的时间限制等等。我认为这里变量太多,很难得出普遍的结论。





