基准测试中Rust现在总体上比C更快 - HACKNEWS


点击标题见原文

黑客新闻讨论:
许多现实世界的C性能要比人们想象的要差很多。在过去的5年中,我花了大量的时间来审查C代码-几乎每次审查中都会弹出昂贵的字符串操作。线性计数是由于使用空终止的字符串以及为附加空终止符的子字符串的额外分配而产生的,或者仅仅是由于无法确定所有权而产生的深拷贝,这比异常情况更为普遍。发生这种情况是因为对于大多数人而言,以null结尾的字符串感觉像是idiomatic的C。
Rust通过slices idiomatic从一开始就避免了这些情况。
 
用C根本无法做任何事情(尤其是可靠的事情),以至于人们通常只能做最简单的事情,这通常意味着简单的数据结构,简单的算法和数组。在许多方面,现代CPU都是经过专门设计的。指针和内存分配通常很麻烦或易变,因此使用像链接列表这样的重指针数据结构非常少见。
 
Brian Cantrill实验:在他的C版本中,他之所以使用AVL树是因为它们易于实现,而他的Rust版本之所以使用B-tree是因为他可以。结果,他对Rust的自然朴素的尝试胜过了他长期优化的C代码。
 
开发人员在性能/正确性之间进行权衡的最佳点在很大程度上取决于领域,尤其是:
-您希望使用多少次?使用次数越多,性能和正确性就越重要。
-您的应用程序有多重要?它越关键,正确性就越重要。
同样,仅通过编写更多测试就可以花费开发人员时间来提高正确性的论点在一定程度上是可行的,但后来收益会递减。使用Rust,您可以消除测试无法达到的某些特定类别的错误。
 
C ++和Rust都具有大致等效的性能上限。没人真正认为Rust现在比C快。
 
Rust可能比C更快,因为通常C编译器必须假定指向内存位置的指针可以重叠(除非您将它们标记为__restrict)。Rust禁止使用别名指针。这在Rust编译器中打开了优化的整个世界。从广义上讲,这就是Rust真正可以比C快的原因。在FORTRAN中也是如此,这是值得的。
 
即使在C语言中,也可以使用strict关键字来告诉编译器2个内存位置可以重叠。当然,程序员会告诉编译器这样做。
我认为Rust和C之间没有公平的比较:C只是一个更高级别的汇编器,如果程序员知道他在做什么,那么他可以100%地利用硬件。这就是为什么C在所有具有低功率微控制器的嵌入式应用程序中仍然使用C的原因,因此必须挤出最佳性能。
对我来说,这就是C和Rust的区别:对于每个快速的Rust程序,都可以保证可以用C(或汇编)编写等效的高性能程序。最糟糕的情况是,您在C中使用内联汇编就可以了。
Rust并非完全相反:如果我为您提供经过高度优化的C程序,那么并非总是可以在Rust中生成等效版本。
同样,这些优化并非总是您想要的。在C语言中,您可以选择优化级别,并且在大多数情况下,至少在我编写的程序上,我选择的优化级别较低。原因是,很多时间性能不是唯一重要的问题,但是可能关系到代码的稳定性(并且具有优化功能的代码编译器更可能包含错误)或调试能力(因此编译器的汇编输出的可读性)。
Rust给出了可怕的汇编代码,无法调试或检查其正确性。您只需要希望编译器不包含错误即可。出于同样的原因,Rust是编写病毒的理想语言,因为很难进行反向工程。
 
Rust似乎更好地使用了并行性。不过,在一项基准测试中(fasta),C gcc仅使用全部4个cpus,而Rust仅使用两个,而仍然获胜。https://benchmarksgame-t
 
如果Rust的实现胜于C的实现,那么荣誉就在于编译器,而不是语言。
 
Rust的性能优势之一是编译器能够明确确定内存别名的能力。别名就是为什么许多数字内核都用Fortran编写的原因,Fortran是一种古老得多的语言,它也严格执行别名,因为它根本不允许重叠引用。
也许还有其他人,但这是我所熟悉的优势。C的含糊不清使得更难实现对现代CPU真正重要的一些优化。
 
我认为对C,C ++和Rust进行基准测试仅对研究人员真正有用。他们都在性能上进行了类似的权衡:迫使您考虑如何使用内存。
 
相对于软件性能而言,高效的表达能力以语言复杂性为代价。C是一种简单的语言,对于简单的软件体系结构,它具有足够的有效表达能力。C ++与之相反。您可以使用其元编程功能来实现令人难以置信的魔术,它可以最佳地表达几乎所有内容,但是如果您想自己学习如何做到这一点,那么上帝会帮助您。Rust位于中间。比C强大得多,不如C ++表现力强。
我曾经写过很多C。它在2021年仍然具有关键的优势,但对于高性能代码却没有,从而放弃了太多的表现力。C ++ 17/20功能强大,但很少有开发人员真正学习如何使用该功能,尽管随着规模和效率变得越来越重要,C ++ 17/20的使用在工业中迅速增长。由于多种原因,Rust在许多方面都是C和C++或Java的继承人。