faces: avoid 40 MB row clone in /faces/embeddings
list_embeddings cloned the full FaceDetectionRow inside the filter_map just to pair it with the base64-encoded embedding. The 2 KB BLOB was already on the row — at 20k unassigned faces that's 40 MB of pointless heap traffic per Apollo cluster-suggest run. Move the bytes out via Option::take() so the row drops the BLOB instead of duplicating it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
14
src/faces.rs
14
src/faces.rs
@@ -884,14 +884,18 @@ impl FaceDao for SqliteFaceDao {
|
||||
// Pair with the base64-encoded embedding string so the handler
|
||||
// doesn't need to know the wire format. Skip rows with NULL
|
||||
// embedding (shouldn't happen on detected rows, but defensive).
|
||||
// `embedding.take()` moves the bytes out of the row so we can
|
||||
// hand the (now-empty-embedding) row plus the encoded string
|
||||
// back to the caller without cloning the whole row — at 20k
|
||||
// rows × 2 KB that clone was 40 MB of pointless heap traffic
|
||||
// per cluster-suggest run.
|
||||
use base64::Engine;
|
||||
Ok(rows
|
||||
.into_iter()
|
||||
.filter_map(|r| {
|
||||
r.embedding.as_ref().map(|bytes| {
|
||||
let b64 = base64::engine::general_purpose::STANDARD.encode(bytes);
|
||||
(r.clone(), b64)
|
||||
})
|
||||
.filter_map(|mut r| {
|
||||
let bytes = r.embedding.take()?;
|
||||
let b64 = base64::engine::general_purpose::STANDARD.encode(&bytes);
|
||||
Some((r, b64))
|
||||
})
|
||||
.collect())
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user