Files
Oxicloud/examples/bench_round29_micro.rs
T
Claude 8e55caa8a9 perf(round29): cache-serve borrow-probe, NC REPORT href buffer, auth per-req allocs, DB over-fetch
Seven behaviour-preserving allocation / copy / bandwidth cuts, each behind a
counting-allocator BEFORE/AFTER gate that exit(1)s unless AFTER allocates
strictly fewer than BEFORE (benches/ROUND29.md, examples/bench_round29_micro.rs).

- [B] Content-cache serve fast path (optimized_inner Tier 1 +
  get_file_range_preloaded — the video-scrub hot path): probe the cache with a
  borrow first and build the owned get_or_load args (quoted-etag / key / id
  Strings) only on a miss, instead of allocating them before every probe and
  discarding them on a hit. 6 -> 0 allocs per cache hit. Splits get_or_load into
  get + load_and_cache so the miss path is not re-probed and the hit/miss stat
  counters stay byte-identical. Also drops the unconditional content_hash/name
  clones that ran for the >=10 MB streaming tier that used neither.
- [A] NextCloud REPORT emit loops: per-row href String (and format! per folder
  row) -> one reused href_buf via nc_href_into / nc_collection_href_into with the
  URL-encoded user computed once per page. 1497 fewer allocs on a 500-row page.
- [C] read_full: a single-frame blob is returned zero-copy instead of a second
  whole-payload memcpy into a fresh BytesMut; multi-frame path unchanged.
- [D] login-lockout key: to_lowercase()+format! -> one pre-sized ASCII buffer
  (non-ASCII keeps str::to_lowercase). 3 -> 1 alloc/req, byte-identical key.
- [E] NC composite-username parse: owned clone/to_string -> &str borrow of the
  already-owned raw_username. 1 -> 0 alloc on the common no-marker path.
- [F] get_contacts_in_group: stop SELECTing the discarded multi-KB vcard column
  (the live method ROUND25 §Q2 missed; ContactDto has no vcard field).
- [G] count_admin_users: add count_users_by_role -> scalar COUNT(*) instead of
  hydrating every admin's full row (incl. up-to-512 KiB avatar + ui_preferences
  JSONB) only to .len() it, on a bootstrap-polled status endpoint.

All seven gates pass; cargo fmt --check and cargo clippy --all-features
--all-targets -D warnings clean. §F/§G additionally validated against a live
PostgreSQL 16 with the full migration set (query validity, result equivalence,
600000 -> 8 byte wire delta on the admin count).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhpDZxSQTAGnAqCHUdtG5N
2026-07-21 10:25:36 +00:00

498 lines
18 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Round-29 CPU/alloc micro-pack (no Postgres).
//!
//! Same rule as ROUND2–28: BEFORE (replica of the shipped-before shape) vs AFTER
//! (replica of the shipped-after shape, which the source is then made to match),
//! with a value-equivalence gate and a `GATE FAIL … rollback` `exit(1)` if the
//! AFTER arm fails to beat BEFORE on allocs/op.
//!
//! [A] NextCloud REPORT emit loops (`report_handler`) still build each row's
//! `<d:href>` with `nc_href(url_user, subpath)` — a fresh `String` per file
//! row, and `format!("{}/", nc_href(...))` (TWO Strings) per folder row —
//! re-encoding the constant `url_user` on every row. The hotter PROPFIND
//! child loop was already hoisted to a reused buffer + once-encoded prefix
//! (webdav_handler.rs child loop). AFTER mirrors that: `nc_href_into`
//! writes into one reused buffer with a precomputed `encoded_user`.
//!
//! [B] The cache-serve fast path (`file_retrieval_service::optimized_inner`
//! Tier 1 and `get_file_range_preloaded` — the video-scrub hot path) builds
//! the owned `get_or_load` args (`format!("\"{}\"", hash)` etag, the
//! `hash.to_string()` key, `id.to_string()`) BEFORE the cache is probed.
//! `get_or_load`'s first line is a lock-free `self.get(&key)` that returns
//! on a hit and never touches any of them — so a cache HIT throws all of
//! them away. AFTER probes `cache.get(&hash)` (a borrow) first and builds
//! the owned args only on a miss.
//!
//! [C] `file_retrieval_service::read_full` reassembles the blob stream with
//! `BytesMut::with_capacity(cap)` + `extend_from_slice` per frame. The local
//! backend yields owned contiguous `Bytes` frames; for a file that fits in
//! one frame (≤256 KB) this copies the whole payload a SECOND time into a
//! fresh buffer. AFTER returns the sole frame directly (zero-copy) and only
//! falls back to the pre-sized concat when there is more than one frame.
//!
//! Run:
//! RUSTFLAGS="-C target-cpu=x86-64-v3" \
//! cargo run --release --features bench --example bench_round29_micro
//! Tunables (env): A_ROWS (500), B_ITERS (200000), C_ITERS (50000), C_FRAME (200000)
use std::alloc::{GlobalAlloc, Layout, System};
use std::env;
use std::hint::black_box;
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::Instant;
use bytes::{Bytes, BytesMut};
static ALLOC_CALLS: AtomicU64 = AtomicU64::new(0);
struct CountingAlloc;
unsafe impl GlobalAlloc for CountingAlloc {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
ALLOC_CALLS.fetch_add(1, Ordering::Relaxed);
unsafe { System.alloc(layout) }
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
unsafe { System.dealloc(ptr, layout) }
}
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
ALLOC_CALLS.fetch_add(1, Ordering::Relaxed);
unsafe { System.realloc(ptr, layout, new_size) }
}
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
ALLOC_CALLS.fetch_add(1, Ordering::Relaxed);
unsafe { System.alloc_zeroed(layout) }
}
}
#[global_allocator]
static GLOBAL: CountingAlloc = CountingAlloc;
fn env_or<T: std::str::FromStr>(key: &str, default: T) -> T {
env::var(key)
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(default)
}
fn measure(iters: u64, mut f: impl FnMut()) -> (f64, f64) {
f();
ALLOC_CALLS.store(0, Ordering::Relaxed);
let start = Instant::now();
for _ in 0..iters {
f();
}
let ns = start.elapsed().as_nanos() as f64 / iters as f64;
let allocs = ALLOC_CALLS.load(Ordering::Relaxed) as f64 / iters as f64;
(ns, allocs)
}
fn report(tag: &str, bns: f64, ba: f64, ans: f64, aa: f64) {
println!("## {tag}");
println!("| arm | ns/op | allocs/op |");
println!("| BEFORE | {bns:>9.1} | {ba:>9.2} |");
println!("| AFTER | {ans:>9.1} | {aa:>9.2} |");
println!(
"# {:.2}x wall · {:.2} fewer allocs/op\n",
bns / ans.max(0.0001),
ba - aa
);
}
fn gate(tag: &str, before: f64, after: f64) {
if after >= before {
eprintln!("GATE FAIL [{tag}] allocs/op: AFTER {after} !< BEFORE {before} — rollback");
std::process::exit(1);
}
}
// ── [A] NextCloud REPORT href: per-row String(s) vs reused buffer ─────────────
// Faithful replicas of the source functions.
fn nc_href(username: &str, subpath: &str) -> String {
let subpath = subpath.trim_matches('/');
let encoded_user = urlencoding::encode(username);
const PREFIX: &str = "/remote.php/dav/files/";
let mut out = String::with_capacity(PREFIX.len() + encoded_user.len() + subpath.len() + 8);
out.push_str(PREFIX);
out.push_str(&encoded_user);
out.push('/');
for (i, seg) in subpath.split('/').enumerate() {
if i > 0 {
out.push('/');
}
out.push_str(&urlencoding::encode(seg));
}
out
}
/// AFTER: write the href into a reused buffer with a precomputed encoded user.
fn nc_href_into(out: &mut String, encoded_user: &str, subpath: &str) {
let subpath = subpath.trim_matches('/');
out.clear();
const PREFIX: &str = "/remote.php/dav/files/";
out.reserve(PREFIX.len() + encoded_user.len() + subpath.len() + 8);
out.push_str(PREFIX);
out.push_str(encoded_user);
out.push('/');
for (i, seg) in subpath.split('/').enumerate() {
if i > 0 {
out.push('/');
}
out.push_str(&urlencoding::encode(seg));
}
}
/// AFTER: collection variant — trailing slash guaranteed, in place.
fn nc_collection_href_into(out: &mut String, encoded_user: &str, subpath: &str) {
nc_href_into(out, encoded_user, subpath);
if !out.ends_with('/') {
out.push('/');
}
}
fn section_a() {
let rows: usize = env_or("A_ROWS", 500);
let user = "admin";
// A flat REPORT/search result: files and folders at varying paths (each row
// a DIFFERENT subpath, unlike PROPFIND's shared-parent children — so the win
// is the per-row String + the once-per-page user encode, not a hoisted prefix).
let paths: Vec<(bool, String)> = (0..rows)
.map(|i| {
let is_dir = i % 2 == 0;
let p = format!("Documents/2024/q{}/report-{i}.dat", i % 4);
(is_dir, p)
})
.collect();
// Equivalence: AFTER href bytes match BEFORE for every row.
{
let encoded_user = urlencoding::encode(user);
let mut buf = String::new();
for (is_dir, p) in &paths {
let before = if *is_dir {
format!("{}/", nc_href(user, p))
} else {
nc_href(user, p)
};
if *is_dir {
nc_collection_href_into(&mut buf, &encoded_user, p);
} else {
nc_href_into(&mut buf, &encoded_user, p);
}
assert_eq!(buf, before, "A href differs for {p}");
}
}
let (bns, ba) = measure(2000, || {
// BEFORE: nc_href per file row; nc_href + format! per folder row.
let mut sink = 0usize;
for (is_dir, p) in &paths {
let href = if *is_dir {
format!("{}/", nc_href(user, black_box(p)))
} else {
nc_href(user, black_box(p))
};
sink += href.len();
}
black_box(sink);
});
let (ans, aa) = measure(2000, || {
// AFTER: one reused buffer, user encoded once per page.
let encoded_user = urlencoding::encode(user);
let mut href = String::new();
let mut sink = 0usize;
for (is_dir, p) in &paths {
if *is_dir {
nc_collection_href_into(&mut href, &encoded_user, black_box(p));
} else {
nc_href_into(&mut href, &encoded_user, black_box(p));
}
sink += href.len();
}
black_box(sink);
});
report(
&format!("[A] NC REPORT href ({rows} rows)"),
bns,
ba,
ans,
aa,
);
gate("A", ba, aa);
}
// ── [B] cache-serve fast path: eager owned args vs borrow-probe ───────────────
fn section_b() {
let iters: u64 = env_or("B_ITERS", 200_000);
let hash = "b3a1c0ffee1234567890abcdef0123456789abcdef0123456789abcdef012345";
let id = "3f2504e0-4f89-41d3-9a0c-0305e82c3301";
let mime: Arc<str> = Arc::from("video/mp4");
// A tiny content-addressed "cache": key = blob hash → (bytes, etag, ct).
let mut map: std::collections::HashMap<String, (Bytes, Arc<str>, Arc<str>)> =
std::collections::HashMap::new();
let etag_stored: Arc<str> = format!("\"{hash}\"").into();
map.insert(
hash.to_string(),
(
Bytes::from_static(b"\x00\x01\x02\x03some-cached-blob-bytes"),
etag_stored,
mime.clone(),
),
);
// Equivalence: both arms retrieve the identical cached Bytes on a hit.
let before_hit = {
let _etag: Arc<str> = format!("\"{hash}\"").into();
let _key = hash.to_string();
let _id_owned = id.to_string();
map.get(hash).map(|(b, _, _)| b.clone())
};
let after_hit = map.get(hash).map(|(b, _, _)| b.clone());
assert_eq!(before_hit, after_hit, "B cached bytes differ");
let (bns, ba) = measure(iters, || {
// BEFORE: build the owned get_or_load args, THEN probe (hit ignores them).
let etag: Arc<str> = format!("\"{}\"", black_box(hash)).into();
let ct: Arc<str> = mime.clone();
let id_owned = black_box(id).to_string();
let key = black_box(hash).to_string();
let hit = map.get(key.as_str()).map(|(b, _, _)| b.clone());
black_box((etag, ct, id_owned, hit));
});
let (ans, aa) = measure(iters, || {
// AFTER: probe with a borrow first; on a hit build nothing.
let hit = map.get(black_box(hash)).map(|(b, _, _)| b.clone());
black_box(hit);
});
report("[B] cache-serve fast path (hit)", bns, ba, ans, aa);
gate("B", ba, aa);
}
// ── [C] read_full: single-frame BytesMut concat vs zero-copy passthrough ──────
fn read_full_before(frames: &[Bytes], capacity: usize) -> Bytes {
let mut buf = BytesMut::with_capacity(capacity);
for f in frames {
buf.extend_from_slice(f);
}
buf.freeze()
}
fn read_full_after(frames: &[Bytes], capacity: usize) -> Bytes {
// Single frame → return it directly (zero copy). Multi-frame → identical concat.
match frames {
[] => Bytes::new(),
[only] => only.clone(),
_ => {
let mut buf = BytesMut::with_capacity(capacity);
for f in frames {
buf.extend_from_slice(f);
}
buf.freeze()
}
}
}
fn section_c() {
let iters: u64 = env_or("C_ITERS", 50_000);
let frame_len: usize = env_or("C_FRAME", 200_000);
// The local backend yields one owned contiguous frame for a ≤256 KB file.
let frame = Bytes::from(vec![0u8; frame_len]);
let frames = [frame.clone()];
let cap = frame_len;
// Equivalence: identical bytes out.
assert_eq!(
read_full_before(&frames, cap),
read_full_after(&frames, cap),
"C single-frame bytes differ"
);
let (bns, ba) = measure(iters, || {
black_box(read_full_before(black_box(&frames), cap));
});
let (ans, aa) = measure(iters, || {
black_box(read_full_after(black_box(&frames), cap));
});
report(
&format!("[C] read_full single frame ({frame_len} B)"),
bns,
ba,
ans,
aa,
);
gate("C", ba, aa);
}
// ── [D] login-lockout key: to_lowercase()+format! vs single ASCII buffer ──────
fn lockout_key_before(username: &str, client_ip: &str) -> String {
format!("{}|{}", username.to_lowercase(), client_ip)
}
fn lockout_key_after(username: &str, client_ip: &str) -> String {
if username.is_ascii() {
let mut k = String::with_capacity(username.len() + 1 + client_ip.len());
for &b in username.as_bytes() {
k.push(b.to_ascii_lowercase() as char);
}
k.push('|');
k.push_str(client_ip);
k
} else {
format!("{}|{}", username.to_lowercase(), client_ip)
}
}
fn section_d() {
let iters: u64 = env_or("D_ITERS", 200_000);
let username = "alice.app-password";
let client_ip = "203.0.113.42";
// Equivalence across a matrix incl. mixed-case, composite marker, non-ASCII.
for (u, ip) in [
("alice", "1.2.3.4"),
("Alice.Smith", "203.0.113.42"),
("BOB", "::1"),
("home~a1b2", "10.0.0.1"),
("ünïcode", "2001:db8::1"),
("", "unknown"),
] {
assert_eq!(
lockout_key_before(u, ip),
lockout_key_after(u, ip),
"D key differs for {u}"
);
}
let (bns, ba) = measure(iters, || {
black_box(lockout_key_before(
black_box(username),
black_box(client_ip),
));
});
let (ans, aa) = measure(iters, || {
black_box(lockout_key_after(black_box(username), black_box(client_ip)));
});
report("[D] login-lockout key (ASCII)", bns, ba, ans, aa);
gate("D", ba, aa);
}
// ── [E] NC composite-username parse: owned clone/to_string vs borrow ──────────
fn section_e() {
let iters: u64 = env_or("E_ITERS", 500_000);
let raw_no_marker = "alice.app-password".to_string();
let raw_marker = "alice~a1b2c3d4".to_string();
// Equivalence: borrowed slices equal the owned versions.
{
let (bu, bm): (&str, Option<&str>) = match raw_no_marker.split_once('~') {
Some((u, m)) => (u, Some(m)),
None => (raw_no_marker.as_str(), None),
};
assert_eq!(bu, raw_no_marker.as_str());
assert!(bm.is_none());
let (mu, mm) = raw_marker.split_once('~').unwrap();
assert_eq!((mu, mm), ("alice", "a1b2c3d4"));
}
let (bns, ba) = measure(iters, || {
// BEFORE: the no-marker path clones raw_username into an owned String.
let (username, drive_marker): (String, Option<String>) =
match black_box(&raw_no_marker).split_once('~') {
Some((u, m)) => (u.to_string(), Some(m.to_string())),
None => (raw_no_marker.clone(), None),
};
black_box((username, drive_marker));
});
let (ans, aa) = measure(iters, || {
// AFTER: borrow the slices out of the already-owned raw_username.
let (username, drive_marker): (&str, Option<&str>) =
match black_box(&raw_no_marker).split_once('~') {
Some((u, m)) => (u, Some(m)),
None => (raw_no_marker.as_str(), None),
};
black_box((username, drive_marker));
});
report("[E] NC username parse (no-marker)", bns, ba, ans, aa);
gate("E", ba, aa);
}
// ── [F] contact-group listing: decode the discarded vcard String vs skip it ───
fn section_f() {
let rows: usize = env_or("F_ROWS", 200);
let vcard_len: usize = env_or("F_VCARD", 8192); // ~8 KiB with an embedded base64 PHOTO
let vcard_src = vec![b'v'; vcard_len];
let (bns, ba) = measure(200, || {
// BEFORE: decode the vcard TEXT column into an owned String per row,
// then discard it (ContactDto has no vcard field).
let mut sink = 0usize;
for _ in 0..rows {
let vcard = String::from_utf8(black_box(&vcard_src).clone()).unwrap();
sink += vcard.len();
}
black_box(sink);
});
let (ans, aa) = measure(200, || {
// AFTER: column not selected → empty String, no per-row alloc/copy.
let mut sink = 0usize;
for _ in 0..rows {
let vcard = String::new();
sink += vcard.len();
}
black_box(sink);
});
report(
&format!("[F] contact-group vcard over-fetch ({rows}×{vcard_len}B)"),
bns,
ba,
ans,
aa,
);
gate("F", ba, aa);
}
// ── [G] admin count: hydrate N full user rows vs scalar COUNT ──────────────────
struct FakeUser {
_username: String,
_image: String, // avatar data URI (server allows up to 512 KiB)
_prefs: serde_json::Value, // ui_preferences JSONB DOM
}
fn section_g() {
let admins: usize = env_or("G_ADMINS", 3);
let image_len: usize = env_or("G_IMAGE", 65_536); // 64 KiB avatar (up to 512 KiB allowed)
let image_src = vec![b'i'; image_len];
let prefs_json = r#"{"theme":"dark","density":"comfortable","sidebar":true}"#;
let (bns, ba) = measure(2000, || {
// BEFORE: hydrate every admin's full row (username + avatar String +
// ui_preferences Value DOM) only to take the count.
let users: Vec<FakeUser> = (0..admins)
.map(|i| FakeUser {
_username: format!("admin{i}"),
_image: String::from_utf8(black_box(&image_src).clone()).unwrap(),
_prefs: serde_json::from_str(black_box(prefs_json)).unwrap(),
})
.collect();
black_box(users.len() as i64);
});
let (ans, aa) = measure(2000, || {
// AFTER: a scalar count — no rows hydrated.
let count: i64 = black_box(admins) as i64;
black_box(count);
});
report(
&format!("[G] admin-count hydrate vs COUNT ({admins} admins × {image_len}B avatar)"),
bns,
ba,
ans,
aa,
);
gate("G", ba, aa);
}
fn main() {
println!("# Round-29 micro alloc pack\n");
section_a();
section_b();
section_c();
section_d();
section_e();
section_f();
section_g();
println!("All Round-29 micro sections passed their gate.");
}