Experimentelle JSONPath-Engine zum Abfragen großer gestreamter Datensätze.
Die rsonpath
Kiste stellt einen JSONPath-Parser und eine Abfrageausführungs-Engine rq
bereit, die SIMD-Anweisungen nutzt, um massive Durchsatzverbesserungen gegenüber herkömmlichen Engines zu erzielen.
Benchmarks von rsonpath
im Vergleich zu einer Referenz-No-SIMD-Engine im Pison-Datensatz. HINWEIS: Die Skala ist logarithmisch!
Um eine JSONPath-Abfrage für eine Datei auszuführen, führen Sie Folgendes aus:
rq '$..a.b' ./file.json
Wenn die Datei weggelassen wird, liest die Engine die Standardeingabe. JSON kann auch inline übergeben werden:
$ rq ' $..a.b ' --json ' {"c":{"a":{"b":42}}} '
42
Weitere Informationen finden Sie in rq --help
oder im rsonbook.
Das Ergebnis der Ausführung einer Abfrage ist eine Folge übereinstimmender Werte, die durch Zeilenumbrüche getrennt sind. Alternativ gibt die Übergabe --result count
nur die Anzahl der Übereinstimmungen zurück, was möglicherweise viel schneller ist. Weitere Ergebnismodi finden Sie auf der Verwendungsseite --help
.
Siehe Releases für vorkompilierte Binärdateien für alle erstklassigen Supportziele.
cargo
Der einfachste Weg zur Installation ist per cargo
.
$ cargo install rsonpath
...
Wenn maximale Geschwindigkeit im Vordergrund steht, sollten Sie rsonpath
mit nativer Unterstützung für CPU-Anweisungen installieren. Dies führt zu einer Binärdatei, die nicht portierbar ist und möglicherweise auf jedem anderen Computer fehlerhaft funktioniert, aber den Durchsatz bis zum letzten Bit ausschöpft.
Führen Sie dazu die folgende cargo install
aus:
$ RUSTFLAGS= " -C target-cpu=native " cargo install rsonpath
...
Schauen Sie sich das entsprechende Kapitel im Rsonbook an.
Das Projekt wird aktiv weiterentwickelt und unterstützt derzeit nur eine Teilmenge der JSONPath-Abfragesprache. Eine Abfrage ist eine Folge von Segmenten, die jeweils einen oder mehrere Selektoren enthalten.
Segment | Syntax | Unterstützt | Seit | Tracking-Problem |
---|---|---|---|---|
Untergeordnetes Segment (einzeln) | [<selector>] | ✔️ | v0.1.0 | |
Untergeordnetes Segment (mehrere) | [<selector1>,...,<selectorN>] | |||
Nachkommendes Segment (einzeln) | ..[<selector>] | ✔️ | v0.1.0 | |
Nachkommendes Segment (mehrere) | ..[<selector1>,...,<selectorN>] |
Wähler | Syntax | Unterstützt | Seit | Tracking-Problem |
---|---|---|---|---|
Wurzel | $ | ✔️ | v0.1.0 | |
Name | .<member> , [<member>] | ✔️ | v0.1.0 | |
Platzhalter | .* , ..* , [*] | ✔️ | v0.4.0 | |
Index (Array-Index) | [<index>] | ✔️ | v0.5.0 | |
Index (Array-Index vom Ende) | [-<index>] | |||
Array-Slice (vorwärts, positive Grenzen) | [<start>:<end>:<step>] | ✔️ | v0.9.0 | #152 |
Array-Slice (vorwärts, beliebige Grenzen) | [<start>:<end>:<step>] | |||
Array-Slice (rückwärts, beliebige Grenzen) | [<start>:<end>:-<step>] | |||
Filter – existenzielle Tests | [?<path>] | #154 | ||
Filter – konstante Atomvergleiche | [?<path> <binop> <atom>] | #156 | ||
Filter – logische Ausdrücke | && , || , ! | |||
Filter – Verschachtelung | [?<expr>[?<expr>]...] | |||
Filter – willkürliche Vergleiche | [?<path> <binop> <path>] | |||
Filter – Funktionserweiterungen | [?func(<path>)] |
Die Kiste wird kontinuierlich für alle Rust-Ziele der Stufe 1 erstellt und es werden kontinuierlich Tests für Ziele durchgeführt, die mit GitHub-Action-Bildern ausgeführt werden können. SIMD wird nur auf x86/x86_64-Plattformen unterstützt.
Ziel-Triple | Nosimd-Build | SIMD-Unterstützung | Kontinuierliche Tests | Tracking-Probleme |
---|---|---|---|---|
aarch64-unknown-linux-gnu | ✔️ | ✔️ | #21, #115 | |
i686-unknown-linux-gnu | ✔️ | ✔️ | ✔️ | |
x86_64-unknown-linux-gnu | ✔️ | ✔️ | ✔️ | |
x86_64-Apple-Darwin | ✔️ | ✔️ | ✔️ | |
i686-pc-windows-gnu | ✔️ | ✔️ | ✔️ | |
i686-pc-windows-msvc | ✔️ | ✔️ | ✔️ | |
x86_64-pc-windows-gnu | ✔️ | ✔️ | ✔️ | |
x86_64-pc-windows-msvc | ✔️ | ✔️ | ✔️ |
Die SIMD-Unterstützung wird modulweise aktiviert. Im Allgemeinen unterstützt jede im letzten Jahrzehnt veröffentlichte CPU AVX2, was alle verfügbaren Optimierungen ermöglicht.
Ältere CPUs mit SSE2 oder höher erhalten teilweise Unterstützung. Sie können mit rq --version
überprüfen, was genau aktiviert ist – überprüfen Sie das Feld SIMD support
:
$ rq --version
rq 0.9.1
Commit SHA: c024e1bab89610455537b77aed249d2a05a81ed6
Features: default,simd
Opt level: 3
Target triple: x86_64-unknown-linux-gnu
Codegen flags: link-arg=-fuse-ld=lld
SIMD support: avx2;fast_quotes;fast_popcnt
Die Fähigkeit fast_quotes
hängt von der Anweisung pclmulqdq
und fast_popcnt
von der Anweisung popcnt
ab.
Nicht alle Selektoren werden unterstützt, siehe die Unterstützungstabelle oben.
Die Engine geht davon aus, dass jedes Objekt im Eingabe-JSON keine doppelten Schlüssel hat. Es kann nicht garantiert werden, dass das Verhalten bei doppelten Schlüsseln stabil ist, aber derzeit stimmt die Engine einfach mit dem ersten solchen Schlüssel überein.
$ rq ' $.key ' --json ' {"key":"value","key":"other value"} '
"value"
Die Engine analysiert keine Unicode-Escape-Sequenzen in Mitgliedsnamen. Dies bedeutet, dass sich ein Schlüssel "a"
von einem Schlüssel "u0041"
unterscheidet, auch wenn sie semantisch dieselbe Zeichenfolge darstellen. Dies entspricht tatsächlich dem Design in Bezug auf die aktuelle JSONPath-Spezifikation. Das Parsen von Unicode-Sequenzen ist kostspielig, daher wurde die Unterstützung dafür zugunsten einer hohen Leistung verschoben. Dies wird als #117 verfolgt.
Das Wesentliche ist: forken, implementieren, hier eine PR machen. Weitere Details finden Sie im CONTRIBUTING-Dokument.
Der Entwicklungsworkflow verwendet just
. Verwenden Sie das mitgelieferte Justfile
. Wenn festgestellt wird, dass in Ihrer Umgebung kein Cargo vorhanden ist, wird Rust mithilfe des rustup
-Tools automatisch für Sie installiert.
$ just build
...
$ just test
...
Benchmarks für rsonpath
befinden sich in einem separaten Repository, das als Git-Submodul in diesem Haupt-Repository enthalten ist.
Der einfachste Weg, alle Benchmarks durchzuführen, ist just bench
. Einzelheiten finden Sie in der README-Datei im Submodul.
Wir haben einen Artikel über rsonpath
, der auf der ASPLOS '24 veröffentlicht werden soll! Sie können es hier lesen.
Dieses Projekt war als meine Abschlussarbeit konzipiert. Einzelheiten zum theoretischen Hintergrund des Motors und Details zu seiner Implementierung finden Sie hier.
Zeigt direkte Abhängigkeiten, vollständige Grafik siehe unten.
cargo tree --package rsonpath --edges normal --depth 1
rsonpath v0.9.1 (/home/mat/src/rsonpath/crates/rsonpath)
├── clap v4.5.4
├── color-eyre v0.6.3
├── eyre v0.6.12
├── log v0.4.21
├── rsonpath-lib v0.9.1 (/home/mat/src/rsonpath/crates/rsonpath-lib)
├── rsonpath-syntax v0.3.1 (/home/mat/src/rsonpath/crates/rsonpath-syntax)
└── simple_logger v4.3.3
[build-dependencies]
├── rustflags v0.1.5
└── vergen v8.3.1
[build-dependencies]
cargo tree --package rsonpath-lib --edges normal --depth 1
rsonpath-lib v0.9.1 (/home/mat/src/rsonpath/crates/rsonpath-lib)
├── arbitrary v1.3.2
├── cfg-if v1.0.0
├── log v0.4.21
├── memmap2 v0.9.4
├── nom v7.1.3
├── rsonpath-syntax v0.3.1 (/home/mat/src/rsonpath/crates/rsonpath-syntax)
├── smallvec v1.13.2
├── static_assertions v1.1.0
├── thiserror v1.0.58
└── vector-map v1.0.1
clap
– Standardkiste zur Bereitstellung der CLI.color-eyre
, eyre
– besser zugängliche Fehlermeldungen für den Parser.log
, simple-logger
– Diagnoseprotokolle während der Kompilierung und Ausführung.cfg-if
– wird zur Unterstützung von SIMD- und Nicht-SIMD-Versionen verwendet.memmap2
– zum schnellen Lesen von Quelldateien über eine Speicherzuordnung anstelle von gepufferten Kopien.nom
– für die Parser-Implementierung.smallvec
– entscheidend für die Leistung kleiner Stapel.static_assertions
– zusätzliche Zuverlässigkeit durch einige konstante Annahmen, die zur Kompilierzeit validiert werden.thiserror
– idiomatische Error
.vector_map
– wird im Abfrage-Compiler für messbar bessere Leistung verwendet. cargo tree --package rsonpath --edges normal
rsonpath v0.9.1 (/home/mat/src/rsonpath/crates/rsonpath)
├── clap v4.5.4
│ ├── clap_builder v4.5.2
│ │ ├── anstream v0.6.13
│ │ │ ├── anstyle v1.0.6
│ │ │ ├── anstyle-parse v0.2.3
│ │ │ │ └── utf8parse v0.2.1
│ │ │ ├── anstyle-query v1.0.2
│ │ │ │ └── windows-sys v0.52.0
│ │ │ │ └── windows-targets v0.52.4
│ │ │ │ ├── windows_aarch64_gnullvm v0.52.4
│ │ │ │ ├── windows_aarch64_msvc v0.52.4
│ │ │ │ ├── windows_i686_gnu v0.52.4
│ │ │ │ ├── windows_i686_msvc v0.52.4
│ │ │ │ ├── windows_x86_64_gnu v0.52.4
│ │ │ │ ├── windows_x86_64_gnullvm v0.52.4
│ │ │ │ └── windows_x86_64_msvc v0.52.4
│ │ │ ├── anstyle-wincon v3.0.2
│ │ │ │ ├── anstyle v1.0.6
│ │ │ │ └── windows-sys v0.52.0 (*)
│ │ │ ├── colorchoice v1.0.0
│ │ │ └── utf8parse v0.2.1
│ │ ├── anstyle v1.0.6
│ │ ├── clap_lex v0.7.0
│ │ ├── strsim v0.11.1
│ │ └── terminal_size v0.3.0
│ │ ├── rustix v0.38.32
│ │ │ ├── bitflags v2.5.0
│ │ │ ├── errno v0.3.8
│ │ │ │ ├── libc v0.2.153
│ │ │ │ └── windows-sys v0.52.0 (*)
│ │ │ ├── libc v0.2.153
│ │ │ ├── linux-raw-sys v0.4.13
│ │ │ └── windows-sys v0.52.0 (*)
│ │ └── windows-sys v0.48.0
│ │ └── windows-targets v0.48.5
│ │ ├── windows_aarch64_gnullvm v0.48.5
│ │ ├── windows_aarch64_msvc v0.48.5
│ │ ├── windows_i686_gnu v0.48.5
│ │ ├── windows_i686_msvc v0.48.5
│ │ ├── windows_x86_64_gnu v0.48.5
│ │ ├── windows_x86_64_gnullvm v0.48.5
│ │ └── windows_x86_64_msvc v0.48.5
│ └── clap_derive v4.5.4 (proc-macro)
│ ├── heck v0.5.0
│ ├── proc-macro2 v1.0.79
│ │ └── unicode-ident v1.0.12
│ ├── quote v1.0.35
│ │ └── proc-macro2 v1.0.79 (*)
│ └── syn v2.0.58
│ ├── proc-macro2 v1.0.79 (*)
│ ├── quote v1.0.35 (*)
│ └── unicode-ident v1.0.12
├── color-eyre v0.6.3
│ ├── backtrace v0.3.71
│ │ ├── addr2line v0.21.0
│ │ │ └── gimli v0.28.1
│ │ ├── cfg-if v1.0.0
│ │ ├── libc v0.2.153
│ │ ├── miniz_oxide v0.7.2
│ │ │ └── adler v1.0.2
│ │ ├── object v0.32.2
│ │ │ └── memchr v2.7.2
│ │ └── rustc-demangle v0.1.23
│ │ [build-dependencies]
│ │ └── cc v1.0.90
│ ├── eyre v0.6.12
│ │ ├── indenter v0.3.3
│ │ └── once_cell v1.19.0
│ ├── indenter v0.3.3
│ ├── once_cell v1.19.0
│ └── owo-colors v3.5.0
├── eyre v0.6.12 (*)
├── log v0.4.21
├── rsonpath-lib v0.9.1 (/home/mat/src/rsonpath/crates/rsonpath-lib)
│ ├── cfg-if v1.0.0
│ ├── log v0.4.21
│ ├── memmap2 v0.9.4
│ │ └── libc v0.2.153
│ ├── nom v7.1.3
│ │ ├── memchr v2.7.2
│ │ └── minimal-lexical v0.2.1
│ ├── rsonpath-syntax v0.3.1 (/home/mat/src/rsonpath/crates/rsonpath-syntax)
│ │ ├── nom v7.1.3 (*)
│ │ ├── owo-colors v4.0.0
│ │ ├── thiserror v1.0.58
│ │ │ └── thiserror-impl v1.0.58 (proc-macro)
│ │ │ ├── proc-macro2 v1.0.79 (*)
│ │ │ ├── quote v1.0.35 (*)
│ │ │ └── syn v2.0.58 (*)
│ │ └── unicode-width v0.1.11
│ ├── smallvec v1.13.2
│ ├── static_assertions v1.1.0
│ ├── thiserror v1.0.58 (*)
│ └── vector-map v1.0.1
│ ├── contracts v0.4.0 (proc-macro)
│ │ ├── proc-macro2 v1.0.79 (*)
│ │ ├── quote v1.0.35 (*)
│ │ └── syn v1.0.109
│ │ ├── proc-macro2 v1.0.79 (*)
│ │ ├── quote v1.0.35 (*)
│ │ └── unicode-ident v1.0.12
│ └── rand v0.7.3
│ ├── getrandom v0.1.16
│ │ ├── cfg-if v1.0.0
│ │ ├── libc v0.2.153
│ │ └── wasi v0.9.0+wasi-snapshot-preview1
│ ├── libc v0.2.153
│ ├── rand_chacha v0.2.2
│ │ ├── ppv-lite86 v0.2.17
│ │ └── rand_core v0.5.1
│ │ └── getrandom v0.1.16 (*)
│ ├── rand_core v0.5.1 (*)
│ └── rand_hc v0.2.0
│ └── rand_core v0.5.1 (*)
├── rsonpath-syntax v0.3.1 (/home/mat/src/rsonpath/crates/rsonpath-syntax) (*)
└── simple_logger v4.3.3
├── colored v2.1.0
│ ├── lazy_static v1.4.0
│ └── windows-sys v0.48.0 (*)
├── log v0.4.21
├── time v0.3.34
│ ├── deranged v0.3.11
│ │ └── powerfmt v0.2.0
│ ├── itoa v1.0.11
│ ├── libc v0.2.153
│ ├── num-conv v0.1.0
│ ├── num_threads v0.1.7
│ │ └── libc v0.2.153
│ ├── powerfmt v0.2.0
│ ├── time-core v0.1.2
│ └── time-macros v0.2.17 (proc-macro)
│ ├── num-conv v0.1.0
│ └── time-core v0.1.2
└── windows-sys v0.48.0 (*)
[build-dependencies]
├── rustflags v0.1.5
└── vergen v8.3.1
├── anyhow v1.0.81
├── cargo_metadata v0.18.1
│ ├── camino v1.1.6
│ │ └── serde v1.0.197
│ │ └── serde_derive v1.0.197 (proc-macro)
│ │ ├── proc-macro2 v1.0.79 (*)
│ │ ├── quote v1.0.35 (*)
│ │ └── syn v2.0.58 (*)
│ ├── cargo-platform v0.1.8
│ │ └── serde v1.0.197 (*)
│ ├── semver v1.0.22
│ │ └── serde v1.0.197 (*)
│ ├── serde v1.0.197 (*)
│ ├── serde_json v1.0.115
│ │ ├── itoa v1.0.11
│ │ ├── ryu v1.0.17
│ │ └── serde v1.0.197 (*)
│ └── thiserror v1.0.58 (*)
├── cfg-if v1.0.0
├── regex v1.10.4
│ ├── aho-corasick v1.1.3
│ │ └── memchr v2.7.2
│ ├── memchr v2.7.2
│ ├── regex-automata v0.4.6
│ │ ├── aho-corasick v1.1.3 (*)
│ │ ├── memchr v2.7.2
│ │ └── regex-syntax v0.8.3
│ └── regex-syntax v0.8.3
├── rustc_version v0.4.0
│ └── semver v1.0.22 (*)
└── time v0.3.34
├── deranged v0.3.11 (*)
├── itoa v1.0.11
├── libc v0.2.153
├── num-conv v0.1.0
├── num_threads v0.1.7 (*)
├── powerfmt v0.2.0
└── time-core v0.1.2
[build-dependencies]
└── rustversion v1.0.14 (proc-macro)