为了比较C和Rust之间的文件I/O性能,我将"test"写入文件100000000次,并从文件100000000次读取4个字节.

与C相比,Rust代码的写入时间是sys的450倍,读取时间是sys的140倍.

我怀疑有更好的方法来实现快速I/O;如何提高Rust中文件I/O的性能?

$ rustc --version
rustc 1.16.0
$ rustc rswrite.rs -C opt-level=3  # Rust for writing
$ time ./rswrite
real    1m8.411s
user    0m3.817s
sys     1m4.533s
$ rustc rsread.rs -C opt-level=3  # Rust for reading
$ time ./rsread
real    0m18.077s
user    0m2.130s
sys     0m15.910s
$ gcc -O3 cwrite.c -ocwrite  # C for writing
$ time ./cwrite
real    0m1.564s
user    0m1.397s
sys     0m0.143s
$ gcc -O3 cread.c -ocread  # C for reading
$ time ./cread
real    0m1.353s
user    0m1.240s
sys     0m0.113s

书写代码:

use std::fs;
use std::io::Write;
fn main() {
    let b = b"test";
    let mut f = fs::File::create("rs.dump").unwrap();
    for _ in 0 .. 100_000_000 {
        f.write(b).unwrap();
    }
}

用于阅读的防 rust 代码:

use std::{fs, mem};
use std::io::Read;
fn main() {
    let mut f = fs::File::open("rs.dump").unwrap();
    let mut b: [u8; 4] = unsafe { mem::uninitialized() };
    for _ in 0 .. 100_000_000 {
        f.read_exact(&mut b).unwrap();
    }
}

C编写代码:

#include <stdio.h>
#define N 100000000
int main()
{
    const char *teststr = "test";
    FILE *fp = fopen("c.dump", "wb");
    unsigned long long i;
    for (i=0; i<N; i++) fwrite(teststr, 4, 1, fp);
    fclose(fp);
    return 0;
}

C阅读代码:

#include <stdio.h>
#define N 100000000

int main() {
    FILE *fp = fopen("c.dump", "rb");
    long long i;
    char buf[4];
    for (i=0; i<N; i++) fread(buf, 4, 1, fp);
    fclose(fp);
    return 0;
}

推荐答案

我的Rust程序没有使用缓冲IO.多亏了Burntsushi和Andrew Henle的 comments ,问题才得以解决.

$ strace ./rswrite
write(3, "test", 4)                     = 4
write(3, "test", 4)                     = 4
...
$ strace ./rswrite
read(3, "test", 4)                      = 4
read(3, "test", 4)                      = 4
...

我修改了代码:

use std::fs;
use std::io::{BufWriter, Write};
fn main() {
    let b = b"test";
    /**** Use std::io::BufWriter ****/
    let mut f = BufWriter::new(fs::File::create("rs.dump").unwrap());
    for _ in 0 .. 100_000_000 {
        f.write(b).unwrap();
    }
}

use std::{fs, mem};
use std::io::{BufReader, Read};
fn main() {
    /**** Use std::io::BufReader ****/
    let mut f = BufReader::new(fs::File::open("rs.dump").unwrap());
    let mut b: [u8; 4] = unsafe { mem::uninitialized() };
    for _ in 0 .. 100_000_000 {
        f.read_exact(&mut b).unwrap();
    }
}

现在,I/O被缓冲.

write(3, "testtesttesttesttesttesttesttest"..., 8192) = 8192
write(3, "testtesttesttesttesttesttesttest"..., 8192) = 8192
...

性能和C一样快.

$ time ./rswrite
real    0m1.341s
user    0m0.213s
sys     0m0.200s
$ time ./rsread_buf
real    0m0.596s
user    0m0.540s
sys     0m0.050s

Rust相关问答推荐

空字符串转换为Box字符串时是否分配?<>

如何将元素添加到向量并返回对该元素的引用?

带扫描的铁 rust 使用滤镜

如何格式化传入Rust中mysql crate的Pool::new的字符串

当对VEC;U8>;使用serde_json时,Base64编码是保护空间的好方法吗?

在IntoIter上调用.by_ref().Take().rev()时会发生什么情况

我如何使用AWS SDK for Rust获取我承担的角色的凭据?

如何实现Deref;多次;?

为什么BufReader实际上没有缓冲短寻道?

tokio::spawn 有和没有异步块

将泛型中的 Box 转换为 rust 中的 Box

当锁被释放时,将锁包装到作用域中是否会发生变化?

Rust 中的生命周期:borrow 的 mut 数据

为什么 `tokio::join!` 宏不需要 Rust 中的 `await` 关键字?

如何判断服务器是否正确接收数据

Rust 中的方法调用有什么区别?

为什么指定生命周期让我返回一个引用?

字符串切片的向量超出范围但原始字符串仍然存在,为什么判断器说有错误?

如何从 Rust 中不同类型的多个部分加入 Path?

如何重写这个通用参数?