|
1 | 1 | use parking_lot::Mutex; |
2 | 2 | use serde_json::{Value, json}; |
| 3 | +use std::cell::RefCell; |
3 | 4 | use std::fs; |
4 | 5 | use std::io::{Error as IoError, ErrorKind}; |
5 | 6 | use std::thread; |
6 | 7 |
|
7 | 8 | use crossbeam_channel::{Receiver, Sender, unbounded}; |
8 | 9 |
|
| 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 | + |
9 | 15 | /// JsonMutexDB provides thread-safe access to a JSON file acting as a simple database. |
10 | 16 | /// It supports asynchronous (batched) updates and fast serialization (using simd-json) |
11 | 17 | /// in compact mode. |
@@ -123,17 +129,36 @@ impl JsonMutexDB { |
123 | 129 | /// The JSON is saved in either pretty printed or compact format based on configuration. |
124 | 130 | pub fn save_sync(&self) -> Result<(), IoError> { |
125 | 131 | let data_guard = self.data.lock(); |
| 132 | + let json_data = &*data_guard; |
| 133 | + |
126 | 134 | 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()))? |
129 | 138 | } 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 | + })? |
133 | 157 | } 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 | + }; |
137 | 162 | fs::write(&self.path, content) |
138 | 163 | } |
139 | 164 |
|
|
0 commit comments