45
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

Organization

RustのファイルI/OにはBufReader, BufWriterを使いましょう、という話

Rustが得意なフレンズになりたくて、人の書いたCのコードを、Rustに写経しています。
で、作っていたら、ファイルI/Oが、悲惨なレベルで遅いことに気づきました。

とても遅いwrite
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();
    }
}
とても遅いread
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();
    }
}

何が悪いか、分かりますか? まぁ、タイトル読めば分かりますよね。
実は、Rustのファイルのwrite, read_exactは、バッファリングされていません。
なので、このコードは、4バイトずつ読み書きするために10万回のシステムコールを呼び出します。
じゃあCのfread, fwriteは? そっちはバッファリングされているらしいのです。

標準入出力ライブラリは、簡単かつ効果のよい、 バッファーリングされたストリーム入出力インターフェースを提供する。

ふぇぇ、manページの最初に書いてあるのに、知らなかったし、考えたこともなかった。

そういうわけなので。ファイルI/Oでは std::io::{BufReader, BufWriter} を使うとCと互角の速度になりました。

ふつうに速いwrite
use std::fs;
use std::io::{BufWriter, Write};
fn main() {
    let b = b"test";
    let mut f = BufWriter::new(fs::File::create("rs.dump").unwrap());
    for _ in 0 .. 100_000_000 {
        f.write(b).unwrap();
    }
}
ふつうに速いread
use std::{fs, mem};
use std::io::{BufReader, Read};
fn main() {
    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();
    }
}

Special Thanks

本気で原因分からなかったので、StackOverflowで質問し、教えていただきました。
http://stackoverflow.com/questions/43028653/rust-file-i-o-is-very-slow-compared-with-c-is-something-wrong/43029048

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
45
Help us understand the problem. What are the problem?