我用50亿字节的内存写入操作测试了`go`和`rust`的性能,发现`go`的内存操作比`rust`快!
我并不是一次性分配50亿字节内存,而是每次调用函数写入100000(大约100K不到一点)字节,反复调用5万次。我测试了两种写入方式,一种是初始化预分配内存的,另一种是初始化不分配内存的。结果是预分配模式下,`go`大大领先`rust`,速度达到`rust`的1.78倍;不预先分配内存模式下,双方性能相当。
`go`源代码(`app.go`和`app_test.go`)
```
//app.go
package main
import (
"fmt"
"time"
)
const L = 100000
const N = 50000
//预分配内存模式
func preAppend() []byte {
buf := make([]byte, 0, L)
for i := 0; i < L; i++ {
buf = append(buf, 's')
}
return buf
}
//不分配内存模式
func normalAppend() []byte {
buf := make([]byte, 0)
for i := 0; i < L; i++ {
buf = append(buf, 's')
}
return buf
}
func main() {
start := time.Now()
for i := 0; i < N; i++ {
preAppend()
}
fmt.Printf("preAppend Time:%v\n", time.Now().Sub(start).Seconds())
start = time.Now()
for i := 0; i < N; i++ {
normalAppend()
}
fmt.Printf("normalAppend Time:%v\n", time.Now().Sub(start).Seconds())
}
//app_test.go
package main
import (
"testing"
)
func TestNormalAppend(t *testing.T) {
for i := 0; i < N; i++ {
normalAppend()
}
println("TestNormalAppend")
}
func TestPreAppend(t *testing.T) {
for i := 0; i < N; i++ {
preAppend()
}
println("TestPreAppend")
}
```
`rust`源代码:
```
//main.rs
use std::time;
const N: isize = 50000;
const L: usize = 100000;
fn main() {
let start = time::SystemTime::now();
for _i in 0..N {
pre_append();
}
let end = time::SystemTime::now();
println!("pre_append Time:{:?}", end.duration_since(start).unwrap());
let start = time::SystemTime::now();
for _i in 0..N {
normal_append();
}
let end = time::SystemTime::now();
println!(
"normal_append Time:{:?}",
end.duration_since(start).unwrap()
);
}
//不分配内存模式
fn normal_append() -> String {
let mut buf = String::new();
let mut i: usize = 0;
while i < L {
buf.push('s');
i += 1;
}
return buf;
}
//预分配内存模式
fn pre_append() -> String {
let mut buf = String::with_capacity(L);
let mut i: usize = 0;
while i < L {
buf.push('s');
i += 1;
}
return buf;
}
#[cfg(test)]
mod tests {
use crate::normal_append;
use crate::pre_append;
use std::fmt::Error;
const N: isize = 50000;
#[test]
fn test_pre_append() -> Result<(), Error> {
for _i in 0..N {
pre_append();
}
Ok(())
}
#[test]
fn test_normal_append() -> Result<(), Error> {
for _i in 0..N {
normal_append();
}
Ok(())
}
}
```
### 下面是各种模式下的运行结果:
#### 测试模式的比拼
`go`语言:
```
$ go test -v .
=== RUN TestNormalAppend
TestNormalAppend
--- PASS: TestNormalAppend (11.51s)
=== RUN TestPreAppend
TestPreAppend
--- PASS: TestPreAppend (6.63s)
PASS
ok app_test_bench 18.146s
```
运行 `TestNormalAppend`的时间是11.51秒。
运行`TestPreAppend`的时间是6.63秒。
`rust`语言:
```
$ cargo t
Compiling string_test v0.1.0 (/home/fuhz/src/rust_test/string_test)
Finished test [unoptimized + debuginfo] target(s) in 0.37s
Running unittests src/main.rs (target/debug/deps/string_test-cf0723c9e88581f5)
running 2 tests
test tests::test_normal_append has been running for over 60 seconds
test tests::test_pre_append has been running for over 60 seconds
test tests::test_pre_append ... ok
test tests::test_normal_append ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 78.64s
```
`test_normal_append`对应`go`程序中的`TestNormalAppend`,`test_pre_append`对应`go`程序中的`TestPreAppend`,两者的运行时间都超过了60秒,无法显示精确时间。
#### Debug模式的比拼
```
$ go build
$ ./app_test_bench
preAppend Time:5.864950476
normalAppend Time:12.123574635
cargo build
Compiling string_test v0.1.0 (/home/fuhz/src/rust_test/string_test)
Finished dev [unoptimized + debuginfo] target(s) in 0.27s
$ target/debug/string_test
pre_append Time:69.011713959s
normal_append Time:69.313903563s
```
`go`程序中,`preAppend`用时5.865秒,`normalAppend`用时12.123秒;`rust`程序中,`pre_append`用时69.012秒,`normal_append`用时69.314秒。
#### Release模式的比拼
```
$ go build -ldflags '-s -w'
$ ./app_test_bench
preAppend Time:6.072494913
normalAppend Time:10.464082479
$ cargo build --release
Compiling string_test v0.1.0 (/home/fuhz/src/rust_test/string_test)
Finished release [optimized] target(s) in 0.30s
$ target/release/string_test
pre_append Time:10.794002015s
normal_append Time:10.808211814s
```
`go`程序中,`preAppend`用时6.072秒,`normalAppend`用时10.464秒;`rust`程序中,`pre_append`用时10.794秒,`normal_append`用时10.808秒。
有疑问加站长微信联系(非本文作者))