最近,我正在学习如何在 Rust 中更快地处理 I/O。我在标准文档中找到了“BufReader”和“BufWriter”,它说这些读取器和写入器使频繁的读取和写入速度更快,因为它有内部缓冲区。
因此,我尝试从由换行符分隔的文件中读取 1,000,000 个整数数据,并将该数据写入标准输出。
使用BufWriter写入 1,000,000 条数据比仅使用 writeln 快得多!宏观如我所料。但是,就BufReader而言, stdin().read_line() 比 BufReader.read_line() 快得多。
这是我的代码。
use std::fmt::Write as FmtWrite;
use std::io::{self, BufRead, BufReader, BufWriter, Read, Write};
use std::time::SystemTime;
fn main() {
let now = SystemTime::now();
// 324 millisec
// let mut input = String::new();
// io::stdin().read_line(&mut input).unwrap();
// let n = input.trim().parse::<usize>().unwrap();
//
// for _ in 0..n {
// input.clear();
// io::stdin().read_line(&mut input).unwrap();
// let num = input.trim().parse::<usize>().unwrap();
// }
// 484 millisec???
let mut input = String::new();
let mut reader = BufReader::new(io::stdin().lock());
reader.read_line(&mut input).unwrap();
let n = input.trim().parse::<usize>().unwrap();
for _ in 0..n {
input.clear();
reader.read_line(&mut input).unwrap();
let num = input.trim().parse::<usize>().unwrap();
}
println!("{}", now.elapsed().unwrap().as_millis());
}
Run Code Online (Sandbox Code Playgroud)
这是我的 input.txt 的样子。
1000000
1
35
620
342
5
... and more ...
Run Code Online (Sandbox Code Playgroud)
正如评论所说,使用 stdin().read_line() 读取大约需要 300 毫秒,但 BufReader.read_line() 从文件中读取 1,000,000 个数据花费了 400 毫秒以上。
为什么 BufReader 速度较慢?我读到 stdin().read_line() 每次调用时都会锁定和解锁 stdin。但是 BufReader 在创建时只锁定 stdin 一次。所以,从逻辑上讲,BufReader 应该更快,对吗?而且它还有缓冲!
我是否误解了BufReader的使用?
任何评论都会有帮助。
每个句柄都是对此进程的输入数据的全局缓冲区的共享引用。可以使用句柄
lock来获得对BufRead方法的完全访问权限(例如,.lines())。否则,对该句柄的读取将相对于其他读取被锁定。
换句话说,Stdin已经缓冲了,再次缓冲只会增加开销。话虽这么说,最有效的解决方案可能是直接锁定Stdin并使用StdinLock:
use std::io::{self, BufRead};
fn main() {
let mut input = String::new();
let mut stdin = io::stdin().lock();
stdin.read_line(&mut input).unwrap();
let n = input.trim().parse::<usize>().unwrap();
for _ in 0..n {
input.clear();
io::stdin().read_line(&mut input).unwrap();
let num = input.trim().parse::<usize>().unwrap();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
560 次 |
| 最近记录: |