Skip to content

Commit

Permalink
get rid of JsonPathFinder and Boxes (#58)
Browse files Browse the repository at this point in the history
* Revert "61 regex perf (#62)"

This reverts commit a07c7b6.

* try to get rid of JsonPathFinder and Boxes
 - JsonPathFinder interface does not really benefit from storing the json or path internally
 - trying to get rid of the Box<> that is used inside of JsonPathFinder

* some clippy fixes

* add benches for find slicing

equal bench with reuse     time:   [510.30 ns 512.16 ns 514.26 ns]
equal bench without reuse  time:   [21.436 µs 21.456 µs 21.479 µs]
regex bench with reuse     time:   [58.875 µs 58.925 µs 58.975 µs]
regex bench without reuse  time:   [85.324 µs 85.416 µs 85.517 µs]
JsonPathInst generation    time:   [23.988 µs 24.019 µs 24.052 µs]
  • Loading branch information
xMAC94x authored Jun 4, 2024
1 parent c1e3221 commit 1d375e6
Show file tree
Hide file tree
Showing 13 changed files with 358 additions and 669 deletions.
96 changes: 48 additions & 48 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,48 @@
* **`0.1.0`**
* Initial implementation
* **`0.1.1`**
* Technical improvements
* **`0.1.2`**
* added a trait to obtain the result from value
* added a method to get the cloned as Value
* change the name of the general method*
* **`0.1.4`**
* add an ability to use references instead of values
* fix some clippy issues
* **`0.1.5`**
* correct grammar for `$.[..]`
* **`0.1.6`**
* add logical OR and logical And to filters
* fix bugs with objects in filters
* add internal macros to generate path objects
* **`0.2.0`**
* add json path value as a result for the library
* add functions (size)
* change a logical operator `size` into function `size()`
* **`0.2.1`**
* changed the contract for length() function.
* **`0.2.2`**
* add ..*
* **`0.2.5`**
* build for tags
* **`0.2.6`**
* make parser mod public
* **`0.3.0`**
* introduce the different behaviour for empty results and non-existing result
* **`0.3.2`**
* make jsonpath inst cloneable.
* **`0.3.3`**
* fix a bug with the logical operators
* **`0.3.4`**
* add a result as a path
* **`0.3.5`**
* add `!` negation operation in filters
* allow using () in filters
* **`0.5`**
* add config for jsonpath
* add an option to add a regex cache for boosting performance
* **`0.5.1`**
* add double quotes for the expressions (before it was only possible to use single quotes)
* add Debug on the JsonPathFinder


- **`0.1.0`**
- Initial implementation
- **`0.1.1`**
- Technical improvements
- **`0.1.2`**
- added a trait to obtain the result from value
- added a method to get the cloned as Value
- change the name of the general method\*
- **`0.1.4`**
- add an ability to use references instead of values
- fix some clippy issues
- **`0.1.5`**
- correct grammar for `$.[..]`
- **`0.1.6`**
- add logical OR and logical And to filters
- fix bugs with objects in filters
- add internal macros to generate path objects
- **`0.2.0`**
- add json path value as a result for the library
- add functions (size)
- change a logical operator `size` into function `size()`
- **`0.2.1`**
- changed the contract for length() function.
- **`0.2.2`**
- add ..\*
- **`0.2.5`**
- build for tags
- **`0.2.6`**
- make parser mod public
- **`0.3.0`**
- introduce the different behaviour for empty results and non-existing result
- **`0.3.2`**
- make jsonpath inst cloneable.
- **`0.3.3`**
- fix a bug with the logical operators
- **`0.3.4`**
- add a result as a path
- **`0.3.5`**
- add `!` negation operation in filters
- allow using () in filters
- **`0.5`**
- add config for jsonpath
- add an option to add a regex cache for boosting performance
- **`0.5.1`**
- add double quotes for the expressions (before it was only possible to use single quotes)
- add Debug on the JsonPathFinder
- **`0.6`**
- allow to reuse regex, that improves performance without needing an internal cache
13 changes: 8 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "jsonpath-rust"
description = "The library provides the basic functionality to find the set of the data according to the filtering query."
version = "0.5.1"
version = "0.6.0"
authors = ["BorisZhguchev <[email protected]>"]
edition = "2018"
license-file = "LICENSE"
Expand All @@ -17,12 +17,15 @@ regex = "1"
pest = "2.0"
pest_derive = "2.0"
thiserror = "1.0.50"
lazy_static = "1.4"
once_cell = "1.19.0"

[dev-dependencies]
lazy_static = "1.0"
criterion = "0.5.1"

[[bench]]
name = "regex_bench"
harness = false
name = "regex"
harness = false

[[bench]]
name = "equal"
harness = false
43 changes: 0 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -389,50 +389,7 @@ fn test() {
** If the value has been modified during the search, there is no way to find a path of a new value.
It can happen if we try to find a length() of array, for in stance.**

## Configuration

The JsonPath provides a wat to configure the search by using `JsonPathConfig`.

```rust
pub fn main() {
let cfg = JsonPathConfig::new(RegexCache::Implemented(DefaultRegexCacheInst::default()));
}
```

### Regex cache
The configuration provides an ability to use a regex cache to improve the [performance](https://github.com/besok/jsonpath-rust/issues/61)

To instantiate the cache needs to use `RegexCache` enum with the implementation of the trait `RegexCacheInst`.
Default implementation `DefaultRegexCacheInst` uses `Arc<Mutex<HashMap<String,Regex>>>`.
The pair of Box<Value> or Value and config can be used:
```rust
pub fn main(){
let cfg = JsonPathConfig::new(RegexCache::Implemented(DefaultRegexCacheInst::default()));
let json = Box::new(json!({
"author":"abcd(Rees)",
}));

let _v = (json, cfg).path("$.[?(@.author ~= '.*(?i)d\\(Rees\\)')]")
.expect("the path is correct");


}
```
or using `JsonPathFinder` :

```rust
fn main() {
let cfg = JsonPathConfig::new(RegexCache::Implemented(DefaultRegexCacheInst::default()));
let finder = JsonPathFinder::from_str_with_cfg(
r#"{"first":{"second":[{"active":1},{"passive":1}]}}"#,
"$.first.second[?(@.active)]",
cfg,
).unwrap();
let slice_of_data: Vec<&Value> = finder.find_slice();
let js = json!({"active":1});
assert_eq!(slice_of_data, vec![JsonPathValue::Slice(&js, "$.first.second[0]".to_string())]);
}
```

## The structure

Expand Down
41 changes: 41 additions & 0 deletions benches/equal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use criterion::{criterion_group, criterion_main, Criterion};
use jsonpath_rust::{JsonPathInst, JsonPathQuery};
use serde_json::json;
use std::str::FromStr;

struct SearchData {
json: serde_json::Value,
path: JsonPathInst,
}

const PATH: &'static str = "$.[?(@.author == 'abcd(Rees)')]";

fn equal_perf_test_with_reuse(cfg: &SearchData) {
let _v = jsonpath_rust::find(&cfg.path, &cfg.json);
}

fn equal_perf_test_without_reuse() {
let json = Box::new(json!({
"author":"abcd(Rees)",
}));

let _v = json.path(PATH).expect("the path is correct");
}

pub fn criterion_benchmark(c: &mut Criterion) {
let data = SearchData {
json: json!({
"author":"abcd(Rees)",
}),
path: JsonPathInst::from_str(PATH).unwrap(),
};
c.bench_function("equal bench with reuse", |b| {
b.iter(|| equal_perf_test_with_reuse(&data))
});
c.bench_function("equal bench without reuse", |b| {
b.iter(|| equal_perf_test_without_reuse())
});
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
48 changes: 48 additions & 0 deletions benches/regex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use criterion::{criterion_group, criterion_main, Criterion};
use jsonpath_rust::{JsonPathInst, JsonPathQuery};
use serde_json::json;
use std::str::FromStr;

struct SearchData {
json: serde_json::Value,
path: JsonPathInst,
}

const PATH: &'static str = "$.[?(@.author ~= '.*(?i)d\\(Rees\\)')]";

fn regex_perf_test_with_reuse(cfg: &SearchData) {
let _v = jsonpath_rust::find(&cfg.path, &cfg.json);
}

fn regex_perf_test_without_reuse() {
let json = Box::new(json!({
"author":"abcd(Rees)",
}));

let _v = json.path(PATH).expect("the path is correct");
}

fn json_path_inst_compiling() {
let _v = JsonPathInst::from_str(PATH).unwrap();
}

pub fn criterion_benchmark(c: &mut Criterion) {
let data = SearchData {
json: json!({
"author":"abcd(Rees)",
}),
path: JsonPathInst::from_str(PATH).unwrap(),
};
c.bench_function("regex bench with reuse", |b| {
b.iter(|| regex_perf_test_with_reuse(&data))
});
c.bench_function("regex bench without reuse", |b| {
b.iter(|| regex_perf_test_without_reuse())
});
c.bench_function("JsonPathInst generation", |b| {
b.iter(|| json_path_inst_compiling())
});
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
40 changes: 0 additions & 40 deletions benches/regex_bench.rs

This file was deleted.

Loading

0 comments on commit 1d375e6

Please sign in to comment.