Skip to content

Commit a588531

Browse files
committed
Optimize JSON serialization in JsonMutexDB with thread-local buffer for fast compact saves
1 parent 04216c4 commit a588531

File tree

1 file changed

+33
-8
lines changed

1 file changed

+33
-8
lines changed

src/lib.rs

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
use parking_lot::Mutex;
22
use serde_json::{Value, json};
3+
use std::cell::RefCell;
34
use std::fs;
45
use std::io::{Error as IoError, ErrorKind};
56
use std::thread;
67

78
use crossbeam_channel::{Receiver, Sender, unbounded};
89

10+
// Thread-local buffer to reuse across saves
11+
thread_local! {
12+
static SERIALIZE_BUF: RefCell<Vec<u8>> = RefCell::new(Vec::with_capacity(1024 * 64)); // 64 KB buffer
13+
}
14+
915
/// JsonMutexDB provides thread-safe access to a JSON file acting as a simple database.
1016
/// It supports asynchronous (batched) updates and fast serialization (using simd-json)
1117
/// in compact mode.
@@ -123,17 +129,36 @@ impl JsonMutexDB {
123129
/// The JSON is saved in either pretty printed or compact format based on configuration.
124130
pub fn save_sync(&self) -> Result<(), IoError> {
125131
let data_guard = self.data.lock();
132+
let json_data = &*data_guard;
133+
126134
let content = if self.pretty {
127-
serde_json::to_string_pretty(&*data_guard)
128-
.map_err(|e| IoError::new(ErrorKind::Other, e.to_string()))
135+
// Use pretty printing via serde_json (fallback)
136+
serde_json::to_string_pretty(json_data)
137+
.map_err(|e| IoError::new(ErrorKind::Other, e.to_string()))?
129138
} else if self.fast_serialization {
130-
// Use simd-json for fast compact serialization.
131-
simd_json::to_string(&*data_guard)
132-
.map_err(|e| IoError::new(ErrorKind::Other, format!("simd_json error: {:?}", e)))
139+
// Use fast compact serialization with a preallocated buffer.
140+
SERIALIZE_BUF.with(|buf_cell| {
141+
let mut buf = buf_cell.borrow_mut();
142+
// Clear the buffer but keep its capacity
143+
buf.clear();
144+
// Here we use simd-json's fast serialization method if available.
145+
// For demonstration, we'll use serde_json's to_vec and then convert to String.
146+
// In practice, you might have a more direct API that writes into buf.
147+
let vec = simd_json::to_vec(json_data).map_err(|e| {
148+
IoError::new(ErrorKind::Other, format!("simd_json error: {:?}", e))
149+
})?;
150+
// Ensure our buffer is large enough and copy the data into it.
151+
buf.extend_from_slice(&vec);
152+
// Convert the pre-allocated buffer into a String.
153+
// Since the output is valid UTF-8, this is safe.
154+
String::from_utf8(buf.clone())
155+
.map_err(|e| IoError::new(ErrorKind::Other, e.to_string()))
156+
})?
133157
} else {
134-
serde_json::to_string(&*data_guard)
135-
.map_err(|e| IoError::new(ErrorKind::Other, e.to_string()))
136-
}?;
158+
// Default compact serialization via serde_json.
159+
serde_json::to_string(json_data)
160+
.map_err(|e| IoError::new(ErrorKind::Other, e.to_string()))?
161+
};
137162
fs::write(&self.path, content)
138163
}
139164

0 commit comments

Comments
 (0)