-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Evaluation of template macros #674
Changes from 1 commit
2185cc3
222bcb2
fb37931
22ca798
f992f86
77fd243
28f6d93
60166cf
435da4c
0de6c1c
2147a6e
c2a700d
002faf1
a176e81
2675d43
bdc89b3
9c2a079
9949390
7901a39
9150196
368cfb4
3943f49
789a325
b02b18c
d169fa8
3247455
528cac1
1b5de55
647571f
01a0265
39df701
f9a0073
04aff35
56b7994
95e885d
1db5b30
158348e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
use criterion::{black_box, criterion_group, criterion_main, Criterion}; | ||
use ion_rs::lazy::decoder::LazyDecoder; | ||
use ion_rs::lazy::encoding::TextEncoding_1_1; | ||
use ion_rs::lazy::r#struct::LazyStruct; | ||
use ion_rs::lazy::reader::{LazyApplicationReader, LazyTextReader_1_0, LazyTextReader_1_1}; | ||
use ion_rs::lazy::value::LazyValue; | ||
use ion_rs::lazy::value_ref::ValueRef; | ||
use ion_rs::IonResult; | ||
use nom::AsBytes; | ||
|
||
pub fn criterion_benchmark(c: &mut Criterion) { | ||
const NUM_VALUES: usize = 10_000; | ||
let data_1_0 = concat!("{", | ||
"'timestamp': 1670446800245,", | ||
"'threadId': 418,", | ||
r#"'threadName': "scheduler-thread-6","#, | ||
r#"'loggerName': "com.example.organization.product.component.ClassName","#, | ||
"'logLevel': INFO,", | ||
r#"'format': "Request status: {} Client ID: {} Client Host: {} Client Region: {} Timestamp: {}","#, | ||
r#"'parameters': ["SUCCESS","example-client-1","aws-us-east-5f-18b4fa","region 4","2022-12-07T20:59:59.744000Z",],"#, | ||
"}" | ||
).repeat(NUM_VALUES); | ||
let template_text = r#" | ||
(macro event (timestamp thread_id thread_name client_num host_id parameters) | ||
{ | ||
'timestamp': timestamp, | ||
'threadId': thread_id, | ||
'threadName': (make_string "scheduler-thread-" thread_name), | ||
'loggerName': "com.example.organization.product.component.ClassName", | ||
'logLevel': (quote INFO), | ||
'format': "Request status: {} Client ID: {} Client Host: {} Client Region: {} Timestamp: {}", | ||
'parameters': [ | ||
"SUCCESS", | ||
(make_string "example-client-" client_num), | ||
(make_string "aws-us-east-5f-" host_id), | ||
parameters | ||
] | ||
} | ||
) | ||
"#; | ||
|
||
let data_1_1 = r#"(:event 1670446800245 418 "6" "1" "18b4fa" (:values "region 4" "2022-12-07T20:59:59.744000Z"))"#.repeat(NUM_VALUES); | ||
|
||
println!("Ion 1.0 data size: {} bytes", data_1_0.len()); | ||
println!("Ion 1.1 data size: {} bytes", data_1_1.len()); | ||
|
||
fn count_value_and_children<D: LazyDecoder>(lazy_value: &LazyValue<'_, D>) -> IonResult<usize> { | ||
use ValueRef::*; | ||
let child_count = match lazy_value.read()? { | ||
List(s) => count_sequence_children(s.iter())?, | ||
SExp(s) => count_sequence_children(s.iter())?, | ||
Struct(s) => count_struct_children(&s)?, | ||
scalar => { | ||
let _ = black_box(scalar); | ||
0 | ||
} | ||
}; | ||
Ok(1 + child_count) | ||
} | ||
|
||
fn count_sequence_children<'a, D: LazyDecoder>( | ||
lazy_sequence: impl Iterator<Item = IonResult<LazyValue<'a, D>>>, | ||
) -> IonResult<usize> { | ||
let mut count = 0; | ||
for value in lazy_sequence { | ||
count += count_value_and_children(&value?)?; | ||
} | ||
Ok(count) | ||
} | ||
|
||
fn count_struct_children<D: LazyDecoder>(lazy_struct: &LazyStruct<'_, D>) -> IonResult<usize> { | ||
let mut count = 0; | ||
for field in lazy_struct { | ||
count += count_value_and_children(&field?.value())?; | ||
} | ||
Ok(count) | ||
} | ||
|
||
c.bench_function("text 1.0: scan all", |b| { | ||
b.iter(|| { | ||
let mut reader = | ||
LazyApplicationReader::<'_, TextEncoding_1_1>::new(data_1_0.as_bytes()).unwrap(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗺️ The 1.0 benchmark tests are using the 1.1 reader because child expression caching is hugely impactful and has not yet been added to the 1.0 decoders. Because Ion 1.1 text is a superset of 1.0 text, the 1.1 reader can process it fine. The measurement should be basically the same as using the 1.0 reader since there are just a few more branches that never get taken, but we'll get this changed over to a proper 1.0 reader once that optimization is backported. I'll add a comment for this. |
||
while let Some(item) = reader.next().unwrap() { | ||
black_box(item); | ||
} | ||
}) | ||
}); | ||
c.bench_function("text 1.0: read all", |b| { | ||
b.iter(|| { | ||
let mut reader = | ||
LazyApplicationReader::<'_, TextEncoding_1_1>::new(data_1_0.as_bytes()).unwrap(); | ||
let mut num_values = 0usize; | ||
while let Some(item) = reader.next().unwrap() { | ||
num_values += count_value_and_children(&item).unwrap(); | ||
} | ||
}) | ||
}); | ||
c.bench_function("text 1.1: scan all", |b| { | ||
b.iter(|| { | ||
let mut reader = LazyTextReader_1_1::new(data_1_1.as_bytes()).unwrap(); | ||
reader.register_template(template_text).unwrap(); | ||
while let Some(item) = reader.next().unwrap() { | ||
black_box(item); | ||
} | ||
}) | ||
}); | ||
c.bench_function("text 1.1: read all", |b| { | ||
b.iter(|| { | ||
let mut reader = LazyTextReader_1_1::new(data_1_1.as_bytes()).unwrap(); | ||
reader.register_template(template_text).unwrap(); | ||
let mut num_values = 0usize; | ||
while let Some(item) = reader.next().unwrap() { | ||
num_values += count_value_and_children(&item).unwrap(); | ||
} | ||
}) | ||
}); | ||
} | ||
|
||
criterion_group!(benches, criterion_benchmark); | ||
criterion_main!(benches); |
This file was deleted.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗺️ All changes in this file are from the rename. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗺️ Slightly awkward syntax here to produce a compact struct instead of a pretty-printed one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you feel like it, you could probably use something like
It's still kind of awkward, but it moves the awkwardness somewhere else. I don't have a preference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm adding another commit that writes out the struct in full (as you've done) and then just roundtrips it to a
String
of compact text.The same commit also makes the
IonEq
trait externally visible so the benchmark can confirm that the 1.0 and 1.1 test data are equivalent before measurement begins.