perf(round25): in-place encrypted decrypt, dedup hash move, dead folder-Query, playlist N+1 fold, contact vcard over-fetch
Five benchmark-gated optimizations from a fresh six-way audit (benches/ROUND25.md), each with a BEFORE/AFTER gate that rolls back if AFTER does not beat BEFORE: - M1 EncryptedBlobBackend::decrypt_bytes: replace split_off (a fresh Vec + full ciphertext memcpy on every decrypted chunk, contradicting its own "in place" doc) with in-place detached decrypt + a zero-copy Bytes::slice past the nonce. Peak RAM per read drops from ~2x to ~1x the payload (-262KB/op at 256KiB; scales with blob size). Plaintext byte-identical; tamper/wrong-key tests pass. - M2 delta commit: move-unzip the owned chunk list instead of a third per-occurrence hash clone (-4000 allocs on a 4000-chunk commit). - M3 folder ZIP download: drop the dead Query<HashMap> extractor it never read (byte-identical response; 5->0 allocs/request). - Q1 public-playlist listing: fold the per-playlist COUNT(*) N+1 into one LEFT JOIN ... GROUP BY via a new inherent repo method (101 -> 1 round-trips, 36x wall on a 100-playlist page). - Q2 contact REST listings (paginated/search/by-group): stop over-fetching the multi-KB vcard TEXT the ContactDto discards, via a shared lite row mapper and narrowed SELECTs (6.4x wall on 1000 contacts with 8KiB vcards). The whole-book vCard export and CardDAV sync paths keep the column. Adds bench_round25_micro (counting allocator tracking count+bytes) and bench_round25_queries (live Postgres), both with equivalence gates and a rollback exit(1). Verified: cargo fmt clean, cargo clippy -D warnings clean, cargo test --lib --features bench = 529 passed / 0 failed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L8gs91AhmazoxMsDcNk3KT
This commit is contained in:
@@ -4,7 +4,6 @@ use axum::{
|
||||
http::{Response, StatusCode, header},
|
||||
response::IntoResponse,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::application::dtos::display_helpers::{
|
||||
@@ -210,7 +209,6 @@ impl FolderHandler {
|
||||
State(state): State<Arc<GlobalAppState>>,
|
||||
auth_user: AuthUser,
|
||||
Path(id): Path<String>,
|
||||
Query(_params): Query<HashMap<String, String>>,
|
||||
) -> impl IntoResponse {
|
||||
tracing::info!("Downloading folder as ZIP: {}", id);
|
||||
|
||||
@@ -421,9 +419,12 @@ pub async fn download_folder_zip(
|
||||
state: State<Arc<GlobalAppState>>,
|
||||
auth_user: AuthUser,
|
||||
path: Path<String>,
|
||||
query: Query<HashMap<String, String>>,
|
||||
) -> impl IntoResponse {
|
||||
FolderHandler::download_folder_zip_impl(state, auth_user, path, query).await
|
||||
// No `Query` extractor: the handler reads only the path `id`. axum ignores
|
||||
// any query string when no extractor is present, so the response is
|
||||
// byte-identical while a per-request HashMap + owned key/value Strings are
|
||||
// no longer parsed and dropped (benches/ROUND25.md §M3).
|
||||
FolderHandler::download_folder_zip_impl(state, auth_user, path).await
|
||||
}
|
||||
|
||||
// ── GET /api/folders/{id}/resources ─────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user