#![allow(unused_results)]
#[path = "support.rs"]
mod support;
use std::time::{Duration, Instant};
use noyalib::{Value, from_str, to_string};
fn bench<F: FnMut()>(iterations: usize, mut f: F) -> Duration {
for _ in 0..iterations / 10 {
f();
}
let start = Instant::now();
for _ in 0..iterations {
f();
}
start.elapsed() / iterations as u32
}
fn fmt_dur(d: Duration) -> String {
if d.as_nanos() < 1_000 {
format!("{:>7.3} ns", d.as_nanos() as f64)
} else if d.as_nanos() < 1_000_000 {
format!("{:>7.3} us", d.as_nanos() as f64 / 1_000.0)
} else {
format!("{:>7.3} ms", d.as_nanos() as f64 / 1_000_000.0)
}
}
fn main() {
support::header("noyalib -- bench");
if cfg!(debug_assertions) {
println!(
" \x1b[33m!\x1b[0m \x1b[90mRunning in DEBUG mode. Use --release for accurate numbers.\x1b[0m\n"
);
}
let simple_yaml = "name: test\nversion: 1\nenabled: true\n";
let nested_yaml = r#"
server:
host: localhost
port: 8080
ssl:
enabled: true
cert: /path/to/cert
key: /path/to/key
database:
host: db.example.com
port: 5432
credentials:
username: admin
password: secret
"#;
let sequence_yaml = r#"
items:
- name: item1
value: 100
tags: [tag1, tag2]
- name: item2
value: 200
tags: [tag3]
- name: item3
value: 300
tags: [tag4, tag5, tag6]
"#;
let large_yaml: String = (0..50).map(|i| format!("key{i}: value{i}\n")).collect();
support::task_with_output("Parsing performance (10k iterations)", || {
vec![
format!(
"simple = {}/op",
fmt_dur(bench(10_000, || {
let _: Value = from_str(simple_yaml).unwrap();
}))
),
format!(
"nested = {}/op",
fmt_dur(bench(10_000, || {
let _: Value = from_str(nested_yaml).unwrap();
}))
),
format!(
"sequence = {}/op",
fmt_dur(bench(10_000, || {
let _: Value = from_str(sequence_yaml).unwrap();
}))
),
format!(
"large = {}/op",
fmt_dur(bench(5_000, || {
let _: Value = from_str(&large_yaml).unwrap();
}))
),
]
});
let simple_v: Value = from_str(simple_yaml).unwrap();
let nested_v: Value = from_str(nested_yaml).unwrap();
let large_v: Value = from_str(&large_yaml).unwrap();
support::task_with_output("Serialization performance (10k iterations)", || {
vec![
format!(
"simple = {}/op",
fmt_dur(bench(10_000, || {
let _ = to_string(&simple_v).unwrap();
}))
),
format!(
"nested = {}/op",
fmt_dur(bench(10_000, || {
let _ = to_string(&nested_v).unwrap();
}))
),
format!(
"large = {}/op",
fmt_dur(bench(5_000, || {
let _ = to_string(&large_v).unwrap();
}))
),
]
});
let nested: Value = from_str(nested_yaml).unwrap();
support::task_with_output("Value operations (100k iterations)", || {
vec![
format!(
"get() = {}/op",
fmt_dur(bench(100_000, || {
let _ = nested.get("server");
}))
),
format!(
"get_path() = {}/op",
fmt_dur(bench(100_000, || {
let _ = nested.get_path("server.ssl.enabled");
}))
),
]
});
support::task_with_output("Bulk processing (1000 documents)", || {
let start = Instant::now();
let values: Vec<Value> = (0..1000)
.map(|i| {
let yaml = format!("id: {i}\nname: item_{i}\nvalue: {}", i * 100);
from_str(&yaml).unwrap()
})
.collect();
let parse_time = start.elapsed();
let start = Instant::now();
let _: Vec<String> = values.iter().map(|v| to_string(v).unwrap()).collect();
let ser_time = start.elapsed();
vec![
format!("parse = {}", fmt_dur(parse_time)),
format!("serialize = {}", fmt_dur(ser_time)),
]
});
support::summary(4);
println!(" \x1b[90mFor precise metrics, run: cargo bench\x1b[0m\n");
}