【发布时间】:2020-05-31 12:25:00
【问题描述】:
我正在尝试获得使用 Rust 读写“大型”CSV 文件的最大速度的指示性度量。
我有一个包含 1 亿行相同行的测试 CSV 文件:
SomeLongStringForTesting1, SomeLongStringForTesting2
此文件在磁盘上的大小为 4.84GB。
我已经编写了(大部分是复制的!)以下使用csv: 1.1.3 crate 的代码:
use std::error::Error;
fn main() {
read_and_write("C:/Dev/100MillionRows.csv", "C:/Dev/100MillionRowsCopy.csv").unwrap();
}
fn read_and_write(in_file_path: &str, out_file_path: &str) -> Result<(), Box<Error>> {
let mut rdr = csv::ReaderBuilder::new()
.has_headers(false)
.from_path(in_file_path)?;
let mut wtr = csv::WriterBuilder::new()
.from_path(out_file_path)?;
for result in rdr.records() {
let record = result?;
wtr.write_record(record.iter())?;
}
wtr.flush()?;
Ok(())
}
在“发布模式”下构建,然后使用以下命令运行:
powershell -Command "Measure-Command {.\target\release\csv-performance.exe}" 产生 72.79 seconds, 71.01 seconds, 70.77 seconds 三个运行。
大致说来,我看到 10GB(结合读取和写入)的 IO 在 70 秒内,相当于 142MB/S。这大约是 Windows 在任务管理器中报告的磁盘使用情况。
这感觉可能很慢,原因如下:
winsat disk -drive c 产生:
Windows System Assessment Tool
> Running: Feature Enumeration ''
> Run Time 00:00:00.00
> Running: Storage Assessment '-drive c -ran -read'
> Run Time 00:00:01.31
> Running: Storage Assessment '-drive c -seq -read'
> Run Time 00:00:05.36
> Running: Storage Assessment '-drive c -seq -write'
> Run Time 00:00:03.17
> Running: Storage Assessment '-drive c -flush -seq'
> Run Time 00:00:00.80
> Running: Storage Assessment '-drive c -flush -ran'
> Run Time 00:00:00.73
> Dshow Video Encode Time 0.00000 s
> Dshow Video Decode Time 0.00000 s
> Media Foundation Decode Time 0.00000 s
> Disk Random 16.0 Read 541.88 MB/s 8.3
> Disk Sequential 64.0 Read 1523.74 MB/s 8.8
> Disk Sequential 64.0 Write 805.49 MB/s 8.3
> Average Read Time with Sequential Writes 0.219 ms 8.6
> Latency: 95th Percentile 1.178 ms 8.2
> Latency: Maximum 7.760 ms 8.2
> Average Read Time with Random Writes 0.199 ms 8.9
这表明我的磁盘(一个相当不错的 SSD)功能更多。
如果我只是复制文件:
powershell -Command "Measure-Command {Copy-Item "C:/Dev/100MillionRows.csv" -Destination "C:/Dev/100MillionRowsCopy.csv"}"
它需要9.97 seconds, 13.85 seconds, 10.90 seconds 运行三遍。以11.57 seconds 取平均值,我看到大约 860 MB/S 的 IO。这更像是我的磁盘的局限性。
显然,在我的代码中读取 CSV 时,我所做的工作比简单的副本要多,但令我惊讶的是它会比副本慢约 6 倍。
对于为什么会出现这种情况以及如何提高我的 Rust 代码的性能的任何想法,是否会感激不尽?我对 Rust 很陌生,所以很可能那里有什么东西!我知道文档 https://docs.rs/csv/1.0.0/csv/tutorial/index.html#performance 的性能部分,但这些似乎是 50% 左右的性能改进,而不是几百%。
更新 1
在不修改代码的情况下,一些进一步的测试表明速率不一致,因为我改变了 1 亿行的行中字符串的大小:
A,B:18 MB/S
SomeLongStringForTesting1, SomeLongStringForTesting2:142 MB/S
AAAA...(A repeated 300 times),BBBB...(B repeated 300 times): 279 MB/S
我将尝试实施记录在案的改进,看看它有什么不同,并且可能还会尝试分析 - 任何有关工具的建议都值得赞赏,否则我将只使用 Google。
【问题讨论】:
-
只是指出执行时间减少>100% 意味着在开始之前完成。所以你可能不得不在这方面调整你的期望。
-
哇!我的意思是我想知道是否有办法让我的代码快 6 倍。在开始之前完成将是一项壮举!
-
使用分析器了解您的代码在哪里花费时间。其他一切都只是猜测。
-
为什么不尝试性能部分中的提示,然后再忽略它们?我写它们是有原因的。如果您的程序仍然比您预期的要慢,请对其进行分析以确定瓶颈。