25 次重大发布
0.26.0 | 2024年4月1日 |
---|---|
0.25.0 | 2023年6月10日 |
0.24.0 | 2023年5月4日 |
0.22.0 | 2022年12月22日 |
0.3.0 | 2017年11月4日 |
#184 在 解析器实现 中
每月466 次下载
用于 15 个crate (10 个直接)
66KB
819 行
pgn-reader
作为Rust库的PGN格式下棋类游戏的快速非分配和流式读取器。
简介
Reader
解析游戏并调用用户提供的 Visitor
的方法。实现自定义访问者允许最大灵活性
- 读取器本身不进行分配(除了单个固定大小的缓冲区)。访问者可以决定如何在内存中表示游戏。
- 读取器不验证走法的合法性。这允许实现对自定义棋类游戏的支持,或延迟走法验证。
- 访问者可以向读取器发出信号,表明它不关心某个游戏或变体。
示例
一个访问者,它计算每场游戏中主线中语法上有效的走法的数量。
use std::io;
use pgn_reader::{Visitor, Skip, BufferedReader, SanPlus};
struct MoveCounter {
moves: usize,
}
impl MoveCounter {
fn new() -> MoveCounter {
MoveCounter { moves: 0 }
}
}
impl Visitor for MoveCounter {
type Result = usize;
fn begin_game(&mut self) {
self.moves = 0;
}
fn san(&mut self, _san_plus: SanPlus) {
self.moves += 1;
}
fn begin_variation(&mut self) -> Skip {
Skip(true) // stay in the mainline
}
fn end_game(&mut self) -> Self::Result {
self.moves
}
}
fn main() -> io::Result<()> {
let pgn = b"1. e4 e5 2. Nf3 (2. f4)
{ game paused due to bad weather }
2... Nf6 *";
let mut reader = BufferedReader::new_cursor(&pgn[..]);
let mut counter = MoveCounter::new();
let moves = reader.read_game(&mut counter)?;
assert_eq!(moves, Some(4));
Ok(())
}
文档
库的状态
API 可能可以更简洁,性能可能比旧版本基于 mmap
的方法略有下降(#12)。这需要一些关注。在我解决这个问题之前,我只会进行最小维护,按照 shakmaty
的要求。
尽管如此,它可能仍然是速度最快的PGN解析器之一。
基准测试(v0.12.0)
在SSD(三星850)、Intel i7-6850K CPU @ 3.60 GHz上使用 lichess_db_standard_rated_2018-10.pgn(2,478,460,000场游戏,52,750 MB未压缩)运行
基准测试 | 时间 | 吞吐量 |
---|---|---|
examples/stats.rs | 111.9s | 471.4 MB/s |
examples/validate.rs | 237.1s | 222.5 MB/s |
examples/parallel_validate.rs | 148.6s | 355.0 MB/s |
scoutfish make |
269.2s | 196.0 MB/s |
grep-F"[事件" -c |
39.2s | 1345.7 MB/s |
examples/stats.rs
与压缩文件
压缩 | 文件大小 | 时间 | 吞吐量 |
---|---|---|---|
无 | 52,750 MB | 111.9s | 471.4 MB/s |
bz2 | 6,226 MB | 1263.1s | 4.9 MB/s |
xz | 6,989 MB | 495.9s | 14.1 MB/s |
gz | 10,627 MB | 335.7s | 31.7 MB/s |
lz4 | 16,428 MB | 180.0s | 91.3 MB/s |
许可证
pgn-reader采用GPL-3.0(或您可选的任何后续版本)许可。请参阅COPYING文件获取完整的许可文本。
依赖项
~1MB
~20K SLoC