C++ vs Rust vs Go 性能比较
C++ vs Rust vs Go 性能比较
本文通过基准测试对C++、Rust和Go三种编程语言编写的gunzip程序进行了性能比较。实验结果显示,在x64 Ubuntu系统上,C++和Rust的运行速度几乎相同,而Go的运行时间是它们的2倍左右。
实验计划
本文要比较的程序是gunzip,它可以解压.gz文件。gunzip有不同的实现,例如用C编写的GNU gzip、用C编写的zlib、用C编写的miniz、用Rust编写的flate2-rs和用Go编写的gzip。但是,除非一种语言是另一种语言的直接移植,由于可能会引入不同实现的噪音,因此无法对两种语言进行准确的基准测试。
为此,我们将选择以下三个方面:
- 用Rust写的gunzip
- C++编写的移植版cpp_gunzip
- Go编写的移植版go_gunzip
尽量减少噪音
还有一个问题——外部库。它们都依赖第三方库计算CRC32校验和,这在解压缩过程中会耗费大量时间。其中,gunzip依赖crc32fast,cpp_gunzip可以链接zlib或FastCrc32,而go_gunzip则依赖Go标准库里的crc32。幸运的是,所有这些程序都支持多线程选项,可以在单独的线程上运行CRC32校验和,因此运行时间与解压缩实现成正比——这是因为解压缩比CRC32校验和耗时更长,因此通过并行化,可以有效地将CRC32校验和的影响降至最低。
让我们做一些实验来验证。我们用两种不同的方式编译cpp_gunzip:(1) 使用FastCrc32;(2) 使用zlib计算CRC32校验和。然后使用单线程和双线程模式比较两者的运行时间,看看有什么不同。
# terminal in Linux
git clone https://github.com/TechHara/cpp_gunzip.git
cd cpp_gunzip
# compile with FastCrc32 vs zlib for CRC32 checksum
cmake -B fastcrc32 -DCMAKE_CXX_FLAGS=-O3 -DUSE_FAST_CRC32=ON . && make -j -C fastcrc32
cmake -B zlib -DCMAKE_CXX_FLAGS=-O3 -DUSE_FAST_CRC32=OFF . && make -j -C zlib
# download linux source code and compress as .gz file
curl -o- https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.8.7.tar.xz | xz -d | gzip > linux.tgz
# run with single-thread
time fastcrc32/gunzip < linux.tgz > linux.tar
time zlib/gunzip < linux.tgz > linux.tar
# run with multi-thread (-t option)
time fastcrc32/gunzip -t < linux.tgz > linux.tar
time zlib/gunzip -t < linux.tgz > linux.tar
在x64 Ubuntu系统上,单线程模式下两个CRC32校验和库的性能差别很大。不过,当我们在多线程模式下运行时,这两个库的运行时间并没有出现预期的差异。因此,这让我们可以最大限度减少基准测试时使用不同CRC32库所带来的噪音。
基准测试
接下来我们将运行基准,使用完全相同的.gz解压缩实现,比较C++与Rust和Go的性能。我们已经运行了C++版本,现在来运行Rust和Go版本。确保在多线程模式下运行,以尽量减少CRC32校验和产生的噪音。
# clone the Rust version
git clone https://github.com/TechHara/gunzip.git
cd gunzip
# build
cargo build -r
# run in multi-threaded mode (-t)
time target/release/gunzip -t < ../linux.tgz > linux.tar
# clone the Go version
cd ..
git clone https://github.com/TechHara/go_gunzip.git
cd go_gunzip
# build
go build
# set max process to 2
export GOMAXPROCS=2
# run in multi-threaded mode (-t)
time ./gunzip -t < ../linux.tgz > linux.tar
好吧,在x64 Ubuntu系统上,C++和Rust的运行速度几乎相同,而Go的运行时间是它们的2倍左右。但与benchmarkgame的数据(4倍)相比,在这个场景下的Go性能还更好一点。
但更好的性能并不意味着更好的语言。在选择语言时,必须考虑应用、开发/维护时间以及安全性。最典型的例子就是Python,它比C语言慢100倍,但却是最流行的编程语言。