perf: round 13 — grouped-view virtualization, notification/login query narrowing, HTTP dedup, locale precompute

Benchmark-gated (BEFORE/AFTER + equivalence/safety gate per change), same
discipline as rounds 2-12. Full write-up in benches/ROUND13.md.

Shipped:
- V1 Grouped views windowed (files route + ResourceList). The grid arm was
  the last unwindowed path (trash is grouped-by-default in grid): each
  swimlane now feeds its own VirtualList, outer container a flex stack.
  vitest gate: 800-item grouped grid mounts <120 .file-item (was 800).
- Q1 get_users_by_ids drops the <=512 KiB avatar image + ui_preferences
  JSONB (notification path never reads them). 30-member fan-out 8.60 ->
  0.25 ms (34.3x), ~7.7 MB off the wire.
- Q2 Login provisioning is_empty() -> SELECT EXISTS for calendar + address
  book (every login). 0.193 -> 0.170 ms, widens with owned-row count.
- Q3 Recent-access prunes only when the upsert inserted (RETURNING xmax=0)
  — a re-access can't grow the set. 0.567 -> 0.324 ms (1.75x).
- L1 Locale supported-codes precomputed once vs rebuilt per anonymous
  request. 616 -> 17.3 ns (35.7x), 18 -> 1 allocs.
- H1 Duplicate /api TraceLayer removed (global stack already wraps it).
  1.86 -> 1.42 us/request, -6 allocs.
- H2 client_ip span field: borrow-only ClientIpDisplay vs owned String.
  187 -> 173 ns, -1 alloc.

Not shipped (discipline): the "media hooks read the blob 3x" lead was a
correctness bug, not a perf dup — the raw-path metadata/faces readers
resolve only for local+unencrypted+single-chunk blobs and silently produce
nothing otherwise. Flagged for maintainers; routing through read_blob_bytes
is a correctness fix (perf-neutral-to-negative), not a benchmark-gated
perf change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BfidAJD5AHw23jtvBUNamB
This commit is contained in:
Claude
2026-07-19 08:17:48 +00:00
parent 50eca0627f
commit f58d72a780
22 changed files with 1411 additions and 61 deletions
+21
View File
@@ -115,6 +115,13 @@ pub struct LocaleRegistry {
/// case-insensitive: input is canonicalised, then probed against
/// this set.
canonical: Arc<HashSet<SmolStr>>,
/// The same codes as an owned `Vec<String>`, materialized ONCE at
/// [`Self::discover`] time. The `Accept-Language` extractor needs a
/// `&[&str]` supported-list per anonymous request; without this it
/// rebuilt N heap `String`s from the registry on every such request
/// (the ROUND10 §15 "process-invariant rebuilt per request" class;
/// benches/ROUND13.md §L1). Borrowed via [`Self::supported_codes`].
supported_codes: Arc<Vec<String>>,
/// The configured fallback locale. Resolved from
/// `OXICLOUD_DEFAULT_LOCALE` at startup; defaults to English when
/// unset.
@@ -200,8 +207,15 @@ impl LocaleRegistry {
sorted.join(", ")
);
// Materialize the supported-codes list once. Order is irrelevant —
// `accept_language::intersection` ranks by the request header's
// q-values, not by this list's order.
let supported_codes: Vec<String> =
canonical.iter().map(|s| s.as_str().to_string()).collect();
Ok(Self {
canonical: Arc::new(canonical),
supported_codes: Arc::new(supported_codes),
default,
})
}
@@ -236,6 +250,13 @@ impl LocaleRegistry {
self.canonical.iter().map(|s| Locale(s.clone()))
}
/// The registry's codes as a borrowable `&[String]`, precomputed at
/// [`Self::discover`] time. Feeds the per-request `Accept-Language`
/// negotiation without re-allocating the list (benches/ROUND13.md §L1).
pub fn supported_codes(&self) -> &[String] {
&self.supported_codes
}
/// Number of locales in the registry. Used by tests + startup logs.
pub fn len(&self) -> usize {
self.canonical.len()