diff --git a/AGENTS.md b/AGENTS.md index a409916..29577bf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,6 +14,6 @@ If you are writing code, write tests first. The tests must pass for your work to If the users asks you to fork off and work on something, this means that you should: 1. Create a temporary directory using `mktemp -d` -2. Create a new branch to work on +2. Create a new branch to work on `git branch xyz` 3. Use git worktree to extract that branch to the temporary directory (i.e., `git worktree add $TMP_DIR -- $BRANCH) 4. Work from that directory (i.e., `cd $TMP_DIR`) diff --git a/benches/benches/hackers_bench.rs b/benches/benches/hackers_bench.rs index 9f6509b..19a0b2e 100644 --- a/benches/benches/hackers_bench.rs +++ b/benches/benches/hackers_bench.rs @@ -205,11 +205,39 @@ fn bench_iterate(c: &mut Criterion) { group.finish(); } +/// Parse, update a field, and serialize back to a buffer. +fn bench_read_update_write(c: &mut Criterion) { + let cases = [ + ("tiny", load("tiny")), + ("small", load("small")), + ("medium", load("medium")), + ]; + + let mut group = c.benchmark_group("read_update_write"); + for (label, maybe_data) in &cases { + let Some(data) = maybe_data else { continue }; + group.throughput(Throughput::Bytes(data.len() as u64)); + group.bench_with_input(BenchmarkId::new("Campaign", label), data, |b, data| { + b.iter(|| { + let campaign = Campaign::new(data).unwrap(); + let mut buf = vec![0u8; data.len() * 2]; + let res = CampaignBuilder::builder(&mut buf) + .name("updated") + .with(&campaign) + .finish(); + black_box(res) + }) + }); + } + group.finish(); +} + criterion_group!( benches, bench_shallow_parse, bench_deep_parse, bench_field_access, - bench_iterate + bench_iterate, + bench_read_update_write ); criterion_main!(benches); diff --git a/upb_test/hackers_bench.c b/upb_test/hackers_bench.c index 2bf7347..10dc3ec 100644 --- a/upb_test/hackers_bench.c +++ b/upb_test/hackers_bench.c @@ -342,6 +342,34 @@ static void fn_count_all_crew(void *state) { upb_Arena_Free(arena); } +static void fn_read_update_write(void *state) { + BenchData *d = state; + upb_Arena *arena = upb_Arena_New(); + Campaign *c = Campaign_parse((const char *)d->data, d->len, arena); + + upb_StringView name = { .data = "updated", .size = 7 }; + Campaign_set_name(c, name); + + size_t len; + char *out = Campaign_serialize(c, arena, &len); + g_sink = (uintptr_t)out; + + upb_Arena_Free(arena); +} + +static void bench_read_update_write(void) { + const char *sizes[] = {"tiny", "small", "medium", NULL}; + printf("\n=== read_update_write ===\n"); + for (int i = 0; sizes[i]; i++) { + BenchData d; + if (!load_bench_data(&d, sizes[i])) continue; + char label[80]; + snprintf(label, sizeof(label), "Campaign_parse+set+serialize/%s [%zu B]", sizes[i], d.len); + run_bench(fn_read_update_write, &d, d.len, label); + free_bench_data(&d); + } +} + static void bench_iterate(void) { const char *sizes[] = {"tiny", "small", "medium", NULL}; printf("\n=== iterate ===\n"); @@ -374,6 +402,7 @@ int main(void) { bench_deep_parse(); bench_field_access(); bench_iterate(); + bench_read_update_write(); printf("\n"); return 0;