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
+49 -16
View File
@@ -329,9 +329,6 @@
// filter on shows the empty state (the host page's `emptyHint` can
// reference `hiddenCount` to say "3 items hidden by the filter").
const isEmpty = $derived(visibleItems.length === 0);
const viewClass = $derived(
filesStore.viewMode === 'grid' ? 'files-grid-view' : 'files-list-view'
);
/** Content width, for computing the grid's column count to match auto-fill. */
let gridWidth = $state(0);
const gridCols = $derived(gridColumns(gridWidth));
@@ -740,8 +737,8 @@
/>
{:else}
<div class="files-container" bind:clientWidth={gridWidth}>
{#if grouped}
<div class={viewClass} style="--files-list-columns: {columns}">
{#if grouped && filesStore.viewMode === 'list'}
<div class="files-list-view" style="--files-list-columns: {columns}">
{#if listHeaderOverride}{@render listHeaderOverride()}{:else}{@render listHeader()}{/if}
{#each sections as section (section.key)}
<div class="rl-swimlane-header" role="rowheader">
@@ -752,17 +749,37 @@
</span>
{/if}
</div>
{#if filesStore.viewMode === 'list'}
<!-- Window each section's rows so a large grouped list (e.g. a big
trash, grouped by remaining days) doesn't mount every row. The
grid-grouped branch stays un-windowed: `files-grid-view` is itself
the card grid and can't host the windowing spacer wrapper. -->
<VirtualList items={section.rows} rowHeight={56} key={(e) => e.id} {row} />
{:else}
{#each section.rows as entry (entry.id)}
{@render row(entry)}
{/each}
{/if}
<!-- Window each section's rows so a large grouped list (e.g. a big
trash, grouped by remaining days) doesn't mount every row. -->
<VirtualList items={section.rows} rowHeight={56} key={(e) => e.id} {row} />
{/each}
</div>
{:else if grouped}
<!-- Grouped GRID: a vertical stack of (header + its own windowed card
grid) per section. The outer is a flex column, NOT `.files-grid-view`
(which is itself a grid and would place each header/VirtualList into a
cell) — the grid lives on each VirtualList's inner window via
`windowClass`, exactly like the flat-grid arm. This was the last
unwindowed path: a grouped-by-default grid (trash) mounted every card
(benches/ROUND13.md §V1). -->
<div class="rl-grouped-grid">
{#each sections as section (section.key)}
<div class="rl-swimlane-header rl-swimlane-header--grid" role="rowheader">
<span class="rl-swimlane-header__label">{section.label}</span>
{#if bucketAction}
<span class="rl-swimlane-header__action">
{@render bucketAction(section.key)}
</span>
{/if}
</div>
<VirtualList
items={section.rows}
columns={gridCols}
rowHeight={240}
windowClass="files-grid-view"
key={(e) => e.id}
{row}
/>
{/each}
</div>
{:else if filesStore.viewMode === 'list'}
@@ -987,6 +1004,22 @@
align-items: center;
}
/* Grouped-grid container: a vertical stack of (header + its own windowed
card grid) per section. Not `.files-grid-view` — the grid is on each
VirtualList's inner window, so this outer element just stacks. */
.rl-grouped-grid {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
/* In the flex stack the `grid-column: 1 / -1` span (meant for the grid
context) is inert; the header spans naturally as a block-level flex
child. */
.rl-swimlane-header--grid {
grid-column: auto;
}
/* Grid view date meta line. */
.grid-meta__line {
display: flex;