【译】用 Rust 实现 csv 解析-part1

随着 csv 1.0 刚刚发布,关于使用 Rust 读取和写入 csv 数据的教程是时候发布了。本教程针对的是刚入门的 Rust 程序员,因此有相当多的示例,并花了一些时间在基础的概念解释上。你可能会发现,其中部分内容很有用,但对有经验的 Rust 程序员来说,快速浏览会更有利。

有关 Rust 的介绍,请参考官方权威指南。如果你还没有写过一行 Rust 代码,但有其他编程语言的经验,那么你可能不需要看权威指南就能读懂本教程。

CSV 库在 Github 上是可用的,并且有相应的文档

最后,这个博客的文章会作为一个教程被包含在 API 文档中,并且后续会有所更新。

目标读者:Rust 初学者。

目录

  • csv 1.0 release
  • Setup
  • 错误处理基础
    • 切换到可恢复的错误处理
  • 读取 CSV
    • 读取 header
    • 分隔符、引号和可变长度的数据记录
    • 使用 Serde 读取
    • 使用 Serde 处理不合法的数据
  • 写入 CSV
    • 写入制表符分隔的数据值
    • 使用 Serde 写入
  • 管道操作
    • 通过搜索筛选
    • 通过人口统计筛选
  • 性能
    • Amortizing 分配
    • Serde 和零分配
    • 不使用标准库进行解析
  • Closing thoughts

CSV 1.0 发布

在开始学习本教程之前,我想简要介绍 1.0 的方向。rust-csv 仓库的第一次提交是 2014.3.22,这比 Rust 1.0 发行版要早了一年多。对于那些从 1.0 之前就开始接触 Rust 的人来说,肯定还记得该语言发生了多大的变化。当然,我也改变了,因为我变得更熟练和习惯于它。然而,从最初的版本开始,csv 库的 API 基本保持不变。这使得提高性能和修复 bug 变得更加困难,最糟糕的是,使用了旧版的序列化架构。

CSV1.0 版本标志着这是一个更快的库,拥有更好的 API,并支持 Rust 序列化框架 Serde

新的 CSV 库附带一个 csv-core crate,它可以在没有 Rust 标准库的情况下解析 CSV 数据,并且主要负责性能改进。特别地,旧版的 CSV 库使用了一种有限状态机,它有很大的开销。而 csv-core crate 将其解析为一个基于 DFA 的表,该表在堆栈上只占用几百个字节。结果,我们得到超过 2 倍的性能改进:

count_game_deserialize_owned_bytes  30,404,805 (85 MB/s)   23,878,089 (108 MB/s)    -6,526,716  -21.47%   x 1.27
count_game_deserialize_owned_str    30,431,169 (85 MB/s)   22,861,276 (113 MB/s)    -7,569,893  -24.88%   x 1.33
count_game_iter_bytes               21,751,711 (119 MB/s)  11,873,257 (218 MB/s)    -9,878,454  -45.41%   x 1.83
count_game_iter_str                 25,609,184 (101 MB/s)  13,769,390 (188 MB/s)   -11,839,794  -46.23%   x 1.86
count_game_read_bytes               12,110,082 (214 MB/s)  6,686,121 (388 MB/s)     -5,423,961  -44.79%   x 1.81
count_game_read_str                 15,497,249 (167 MB/s)  8,269,207 (314 MB/s)     -7,228,042  -46.64%   x 1.87
count_mbta_deserialize_owned_bytes  5,779,138 (125 MB/s)   3,775,874 (191 MB/s)     -2,003,264  -34.66%   x 1.53
count_mbta_deserialize_owned_str    5,777,055 (125 MB/s)   4,353,921 (166 MB/s)     -1,423,134  -24.63%   x 1.33
count_mbta_iter_bytes               3,991,047 (181 MB/s)   1,805,387 (400 MB/s)     -2,185,660  -54.76%   x 2.21
count_mbta_iter_str                 4,726,647 (153 MB/s)   2,354,842 (307 MB/s)     -2,371,805  -50.18%   x 2.01
count_mbta_read_bytes               2,690,641 (268 MB/s)   1,253,111 (577 MB/s)     -1,437,530  -53.43%   x 2.15
count_mbta_read_str                 3,399,631 (212 MB/s)   1,743,035 (415 MB/s)     -1,656,596  -48.73%   x 1.95
count_nfl_deserialize_owned_bytes   10,608,513 (128 MB/s)  5,828,747 (234 MB/s)     -4,779,766  -45.06%   x 1.82
count_nfl_deserialize_owned_str     10,612,366 (128 MB/s)  6,814,770 (200 MB/s)     -3,797,596  -35.78%   x 1.56
count_nfl_iter_bytes                6,798,767 (200 MB/s)   2,564,448 (532 MB/s)     -4,234,319  -62.28%   x 2.65
count_nfl_iter_str                  7,888,662 (172 MB/s)   3,579,865 (381 MB/s)     -4,308,797  -54.62%   x 2.20
count_nfl_read_bytes                4,588,369 (297 MB/s)   1,911,120 (714 MB/s)     -2,677,249  -58.35%   x 2.40
count_nfl_read_str                  5,755,926 (237 MB/s)   2,847,833 (479 MB/s)     -2,908,093  -50.52%   x 2.02
count_pop_deserialize_owned_bytes   11,052,436 (86 MB/s)   8,848,364 (108 MB/s)     -2,204,072  -19.94%   x 1.25
count_pop_deserialize_owned_str     11,054,638 (86 MB/s)   9,184,678 (104 MB/s)     -1,869,960  -16.92%   x 1.20
count_pop_iter_bytes                6,190,345 (154 MB/s)   3,110,704 (307 MB/s)     -3,079,641  -49.75%   x 1.99
count_pop_iter_str                  7,679,804 (124 MB/s)   4,274,842 (223 MB/s)     -3,404,962  -44.34%   x 1.80
count_pop_read_bytes                3,898,119 (245 MB/s)   2,218,535 (430 MB/s)     -1,679,584  -43.09%   x 1.76
count_pop_read_str                  5,195,237 (183 MB/s)   3,209,998 (297 MB/s)     -1,985,239  -38.21%   x 1.62

以上就是所有的介绍了,我们可以开始了!

posted @ 2020-10-25 18:41  suhanyujie  阅读(468)  评论(0编辑  收藏  举报