Skip to content

Commit

Permalink
feat: add benches for jq
Browse files Browse the repository at this point in the history
  • Loading branch information
karatakis committed Nov 28, 2024
1 parent 5cbe15c commit c59044e
Show file tree
Hide file tree
Showing 3 changed files with 237 additions and 2 deletions.
96 changes: 96 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 16 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,32 @@ indexmap = "2.6.0"
serde_json_borrow = "0.7.1"
nom = "8.0.0-alpha2"
anyhow = "1.0.93"
jaq-core = { version = "2" }
jaq-std = { version = "2" }
jaq-json = { version = "1.0.0", features = ["serde_json"]}

[dependencies]
serde_json = { workspace = true }
tailcall-template = { path = "./tailcall-template" }
jaq-core = { workspace = true }
jaq-std = { workspace = true }
jaq-json = { workspace = true }

[dev-dependencies]
gh-workflow = "0.4.1"
pest = "2.7.14"
pest_derive = {version = "2.7.14"}
criterion = "0.5.1"
serde_json = "1.0.133"
nom = "8.0.0-alpha2"
serde_json = { workspace = true }
nom = { workspace = true }

[workspace]
members = ["tailcall-template"]

[[bench]]
name = "json_benches"
harness = false

[[bench]]
name = "jaq"
harness = false
125 changes: 125 additions & 0 deletions benches/jaq.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
use jaq_json::Val;

Check warning on line 1 in benches/jaq.rs

View workflow job for this annotation

GitHub Actions / Build and Test

Diff in /home/runner/work/tailcall-template/tailcall-template/benches/jaq.rs
use serde_json::json;
use criterion::{criterion_group, criterion_main, Criterion};
use tailcall_template::mustache::{Mustache, Segment};
use jaq_core::{load, Ctx, Native, RcIter};
use load::{Arena, File, Loader};

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

pub fn criterion_benchmark(c: &mut Criterion) {
// BASIC SCENARIO
{
let data = json!({"key": "42"});
let expected = "Value: 42".to_string();
{
let mustache = Mustache::from(vec![
Segment::Literal("Value: ".to_string()),

Check warning on line 18 in benches/jaq.rs

View workflow job for this annotation

GitHub Actions / Build and Test

Diff in /home/runner/work/tailcall-template/tailcall-template/benches/jaq.rs
Segment::Expression(vec!["key".to_string()]),
]);
c.bench_function("basic_mustache", |b| b.iter(|| bench_mustache(&data, &mustache, &expected)));
}
{
let program = File { code: "\"Value: \" + .key", path: () };

// start out only from core filters,
// which do not include filters in the standard library
// such as `map`, `select` etc.
let loader = Loader::new([]);
let arena = Arena::default();

// parse the filter
let modules = loader.load(&arena, program).unwrap();

Check warning on line 33 in benches/jaq.rs

View workflow job for this annotation

GitHub Actions / Build and Test

Diff in /home/runner/work/tailcall-template/tailcall-template/benches/jaq.rs

// compile the filter
let filter: jaq_core::Filter<Native<Val>> = jaq_core::Compiler::<_, Native<_>>::default()
.compile(modules)
.unwrap();

c.bench_function("basic_jq", |b| b.iter(|| bench_jq(&data, &filter, &expected)));
}
}
// COMPLEX SCENARIO
{
let data = json!({"user": "Alice", "age": 30});
let expected = "User: Alice, Age: 30".to_string();
{
let mustache = Mustache::from(vec![
Segment::Literal("User: ".to_string()),
Segment::Expression(vec!["user".to_string()]),
Segment::Literal(", Age: ".to_string()),

Check warning on line 51 in benches/jaq.rs

View workflow job for this annotation

GitHub Actions / Build and Test

Diff in /home/runner/work/tailcall-template/tailcall-template/benches/jaq.rs
Segment::Expression(vec!["age".to_string()]),
]);
c.bench_function("complex_mustache", |b| b.iter(|| bench_mustache(&data, &mustache, &expected)));
}
{
let program = File { code: "\"User: \" + .user + \", Age: \" + (.age | tostring)", path: () };
let loader = Loader::new(jaq_std::defs());
let arena = Arena::default();
let modules = loader.load(&arena, program).unwrap();
let filter = jaq_core::Compiler::<_, Native<_>>::default()
.with_funs(jaq_std::funs())
.compile(modules)

Check warning on line 63 in benches/jaq.rs

View workflow job for this annotation

GitHub Actions / Build and Test

Diff in /home/runner/work/tailcall-template/tailcall-template/benches/jaq.rs
.unwrap();

c.bench_function("complex_jq", |b| b.iter(|| bench_jq(&data, &filter, &expected)));
}
}
// NESTED SCENARIO
{
let data = json!({
"user": {
"name": "Alice",
"details": {
"age": 30,
"location": {
"city": "Wonderland",
"country": "Fantasy"
}
}
}
});
let expected = "User: Alice, Age: 30, Location: Wonderland, Country: Fantasy".to_string();
{
let mustache = Mustache::from(vec![
Segment::Literal("User: ".to_string()),

Check warning on line 86 in benches/jaq.rs

View workflow job for this annotation

GitHub Actions / Build and Test

Diff in /home/runner/work/tailcall-template/tailcall-template/benches/jaq.rs
Segment::Expression(vec!["user".to_string(), "name".to_string()]),
Segment::Literal(", Age: ".to_string()),
Segment::Expression(vec!["user".to_string(), "details".to_string(), "age".to_string()]),
Segment::Literal(", Location: ".to_string()),
Segment::Expression(vec!["user".to_string(), "details".to_string(), "location".to_string(), "city".to_string()]),
Segment::Literal(", Country: ".to_string()),
Segment::Expression(vec!["user".to_string(), "details".to_string(), "location".to_string(), "country".to_string()]),
]);
c.bench_function("nested_mustache", |b| b.iter(|| bench_mustache(&data, &mustache, &expected)));
}
{
let program = File { code: "\"User: \" + .user.name + \", Age: \" + (.user.details.age | tostring) + \", Location: \" + .user.details.location.city + \", Country: \" + .user.details.location.country", path: () };
let loader = Loader::new(jaq_std::defs());
let arena = Arena::default();
let modules = loader.load(&arena, program).unwrap();
let filter = jaq_core::Compiler::<_, Native<_>>::default()
.with_funs(jaq_std::funs())
.compile(modules)

Check warning on line 104 in benches/jaq.rs

View workflow job for this annotation

GitHub Actions / Build and Test

Diff in /home/runner/work/tailcall-template/tailcall-template/benches/jaq.rs
.unwrap();

c.bench_function("nested_jq", |b| b.iter(|| bench_jq(&data, &filter, &expected)));
}
}
}

fn bench_mustache(data: &serde_json::Value, mustache: &Mustache, expected: &str) {
let result = mustache.render(data);
assert_eq!(result, expected.to_string());
}

fn bench_jq(data: &serde_json::Value, filter: &jaq_core::Filter<Native<Val>>, expected: &str) {
let inputs = RcIter::new(core::iter::empty());

// iterator over the output values
let mut out = filter.run((Ctx::new([], &inputs), Val::from(data.clone())));

assert_eq!(out.next(), Some(Ok(Val::from(expected.to_string()))));
assert_eq!(out.next(), None);
}

0 comments on commit c59044e

Please sign in to comment.