Skip to content

Commit ff117f9

Browse files
committed
perf(sqlite-native): avoid cloning cached read chunks
1 parent bde5c19 commit ff117f9

1 file changed

Lines changed: 24 additions & 23 deletions

File tree

  • rivetkit-typescript/packages/sqlite-native/src

rivetkit-typescript/packages/sqlite-native/src/vfs.rs

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -413,20 +413,18 @@ unsafe extern "C" fn kv_io_read(
413413
let end_chunk = (offset + requested_length - 1) / kv::CHUNK_SIZE;
414414

415415
let mut chunk_keys_to_fetch = Vec::new();
416-
let mut buffered_chunks: HashMap<usize, Vec<u8>> = HashMap::new();
416+
let mut buffered_chunks = HashMap::new();
417+
// Skip fetching chunks already present in the dirty buffer (batch mode) or read cache.
417418
for chunk_idx in start_chunk..=end_chunk {
418-
// Check dirty buffer first (batch mode writes).
419419
if state.batch_mode {
420-
if let Some(buffered) = state.dirty_buffer.get(&(chunk_idx as u32)) {
421-
buffered_chunks.insert(chunk_idx, buffered.clone());
420+
if state.dirty_buffer.contains_key(&(chunk_idx as u32)) {
422421
continue;
423422
}
424423
}
425-
// Check read cache.
426424
let key = kv::get_chunk_key(file.file_tag, chunk_idx as u32);
427425
if let Some(read_cache) = state.read_cache.as_ref() {
428426
if let Some(cached) = read_cache.get(key.as_slice()) {
429-
buffered_chunks.insert(chunk_idx, cached.clone());
427+
buffered_chunks.insert(chunk_idx, cached.as_slice());
430428
continue;
431429
}
432430
}
@@ -440,29 +438,24 @@ unsafe extern "C" fn kv_io_read(
440438
}
441439
} else {
442440
match ctx.kv_get(chunk_keys_to_fetch) {
443-
Ok(resp) => {
444-
if let Some(read_cache) = state.read_cache.as_mut() {
445-
for (key, value) in resp.keys.iter().zip(resp.values.iter()) {
446-
if !value.is_empty() {
447-
read_cache.insert(key.clone(), value.clone());
448-
}
449-
}
450-
}
451-
resp
452-
}
441+
Ok(resp) => resp,
453442
Err(_) => return SQLITE_IOERR_READ,
454443
}
455444
};
456445
let value_map = build_value_map(&resp);
457446

458447
for chunk_idx in start_chunk..=end_chunk {
459-
let chunk_data: Option<&[u8]> = buffered_chunks
460-
.get(&chunk_idx)
461-
.map(|v| v.as_slice())
462-
.or_else(|| {
463-
let key = kv::get_chunk_key(file.file_tag, chunk_idx as u32);
464-
value_map.get(key.as_slice()).copied()
465-
});
448+
let chunk_key = kv::get_chunk_key(file.file_tag, chunk_idx as u32);
449+
let chunk_data = if state.batch_mode {
450+
state
451+
.dirty_buffer
452+
.get(&(chunk_idx as u32))
453+
.map(|buffered| buffered.as_slice())
454+
} else {
455+
None
456+
}
457+
.or_else(|| buffered_chunks.get(&chunk_idx).copied())
458+
.or_else(|| value_map.get(chunk_key.as_slice()).copied());
466459
let chunk_offset = chunk_idx * kv::CHUNK_SIZE;
467460
let read_start = offset.saturating_sub(chunk_offset);
468461
let read_end = std::cmp::min(kv::CHUNK_SIZE, offset + requested_length - chunk_offset);
@@ -485,6 +478,14 @@ unsafe extern "C" fn kv_io_read(
485478
}
486479
}
487480

481+
if let Some(read_cache) = state.read_cache.as_mut() {
482+
for (key, value) in resp.keys.iter().zip(resp.values.iter()) {
483+
if !value.is_empty() {
484+
read_cache.insert(key.clone(), value.clone());
485+
}
486+
}
487+
}
488+
488489
let actual_bytes = std::cmp::min(requested_length, file_size - offset);
489490
if actual_bytes < requested_length {
490491
buf[actual_bytes..].fill(0);

0 commit comments

Comments
 (0)