#json-parser #json #simd #data-analytics #pikkr

pikkr-annika

在Rust中直接提取值而不进行标记化操作的JSON解析器。由于Annika的编译问题,由Annika重新上传。

1 个不稳定版本

使用旧的Rust 2015

0.16.1 2021年2月19日

#2499 in 解析实现


用于battlesearch

MIT/Apache

150KB
3.5K SLoC

Pikkr

Crates.io version shield Build Status

在Rust中直接提取值而不进行标记化操作的JSON解析器

摘要

Pikkr是一个在Rust中直接提取值而不进行标记化操作的JSON解析器。这个JSON解析器是基于Y. Li, N. R. Katsipoulakis, B. Chandramouli, J. Goldstein, and D. Kossmann. Mison: a fast JSON parser for data analytics. In VLDB, 2017

这个JSON解析器在不需要使用有限状态机(FSM)和进行标记化操作的情况下从JSON记录中提取值。它按照以下步骤解析JSON记录

  1. [索引] 使用SIMD指令和位操作创建索引,该索引将查询字段的逻辑位置映射到它们的物理位置。
  2. [基本解析] 通过使用在前面过程中创建的索引扫描JSON记录以找到查询字段的值,并在早期阶段学习它们的逻辑位置(即JSON结构的模式)。
  3. [推测解析] 使用学习到的结果信息推测查询字段的逻辑位置,在后期阶段直接跳转到它们的物理位置并提取值。如果推测失败,则回退到基本解析。

当在JSON数据流或JSON集合中存在有限数量的不同JSON结构变体时,这个JSON解析器表现良好,这在数据分析领域是一个常见的情况。

请阅读开头段落中提到的论文,以了解JSON解析算法的详细信息。

性能

基准测试结果

硬件

Model Name: MacBook Pro
Processor Name: Intel Core i7
Processor Speed: 3.3 GHz
Number of Processors: 1
Total Number of Cores: 2
L2 Cache (per Core): 256 KB
L3 Cache: 4 MB
Memory: 16 GB

Rust

$ cargo --version
cargo 0.23.0-nightly (34c0674a2 2017-09-01)

$ rustc --version
rustc 1.22.0-nightly (d93036a04 2017-09-07)

Crates

JSON数据

基准测试代码

示例

代码

extern crate pikkr;

fn main() {
    let queries = vec![
        "$.f1".as_bytes(),
        "$.f2.f1".as_bytes(),
    ];
    let train_num = 2; // Number of records used as training data
                       // before Pikkr starts speculative parsing.
    let mut p = match pikkr::Pikkr::new(&queries, train_num) {
        Ok(p) => p,
        Err(err) => panic!("There was a problem creating a JSON parser: {:?}", err.kind()),
    };
    let recs = vec![
        r#"{"f1": "a", "f2": {"f1": 1, "f2": true}}"#,
        r#"{"f1": "b", "f2": {"f1": 2, "f2": true}}"#,
        r#"{"f1": "c", "f2": {"f1": 3, "f2": true}}"#, // Speculative parsing starts from this record.
        r#"{"f2": {"f2": true, "f1": 4}, "f1": "d"}"#,
        r#"{"f2": {"f2": true, "f1": 5}}"#,
        r#"{"f1": "e"}"#
    ];
    for rec in recs {
        match p.parse(rec.as_bytes()) {
            Ok(results) => {
                for result in results {
                    print!("{} ", match result {
                        Some(result) => String::from_utf8(result.to_vec()).unwrap(),
                        None => String::from("None"),
                    });
                }
                println!();
            },
            Err(err) => println!("There was a problem parsing a record: {:?}", err.kind()),
        }
    }
    /*
    Output:
        "a" 1
        "b" 2
        "c" 3
        "d" 4
        None 5
        "e" None
    */
}

构建

$ cargo --version
cargo 0.23.0-nightly (34c0674a2 2017-09-01) # Make sure that nightly release is being used.
$ RUSTFLAGS="-C target-cpu=native" cargo build --release

运行

$ ./target/release/[package name]
"a" 1
"b" 2
"c" 3
"d" 4
None 5
"e" None

文档

限制

贡献

欢迎任何形式的贡献(例如评论、建议、问题、错误报告和拉取请求)。

依赖项