@@ -18,6 +18,7 @@
//!
//! The store owns the file; concurrent writers are not supported.
+use bincode::config::{Configuration, Fixint, LittleEndian, NoLimit};
use indexmap::IndexMap;
use serde::{Serialize, de::DeserializeOwned};
use std::fs::{self, File, OpenOptions};
@@ -25,6 +26,12 @@
use std::io::{self, BufWriter, ErrorKind, Read, Write};
use std::path::{Path, PathBuf};
+const BINCODE_CONFIG: Configuration<LittleEndian, Fixint, NoLimit> =
+ bincode::config::standard()
+ .with_fixed_int_encoding()
+ .with_little_endian()
+ .with_no_limit();
+
const LEN_BYTES: usize = 4;
const TAG_INSERT: u8 = 0;
const TAG_REMOVE: u8 = 1;
@@ -51,7 +58,7 @@
compact_ratio: 2.0,
min_compact_bytes: 1 << 20,
sync_on_write: false,
- buf_capacity: 1024 * 1024,
+ buf_capacity: 2 * 1024 * 1024,
}
}
}
@@ -124,15 +131,21 @@
let body = &buf[payload_start + 1..payload_end];
match tag {
TAG_INSERT => {
- let (k, v): (K, V) = match bincode::deserialize(body) {
- Ok(r) => r,
+ let (k, v): (K, V) = match bincode::serde::decode_from_slice(
+ body,
+ BINCODE_CONFIG,
+ ) {
+ Ok((r, _len)) => r,
Err(_) => break,
};
map.insert(k, v);
}
TAG_REMOVE => {
- let k: K = match bincode::deserialize(body) {
- Ok(r) => r,
+ let k: K = match bincode::serde::decode_from_slice(
+ body,
+ BINCODE_CONFIG,
+ ) {
+ Ok((r, _len)) => r,
Err(_) => break,
};
map.shift_remove(&k);
@@ -160,7 +173,11 @@
live_records,
total_records,
cfg,
- scratch: Vec::with_capacity(256),
+ scratch: {
+ let mut s = Vec::with_capacity(256);
+ s.extend_from_slice(&[0u8; LEN_BYTES]);
+ s
+ },
})
}
@@ -224,10 +241,9 @@
/// [`IndexMap::insert`] semantics).
#[inline]
pub fn insert(&mut self, k: K, v: V) -> io::Result<Option<V>> {
- self.scratch.clear();
- self.scratch.extend_from_slice(&[0u8; LEN_BYTES]);
+ self.scratch.truncate(LEN_BYTES);
self.scratch.push(TAG_INSERT);
- bincode::serialize_into(&mut self.scratch, &(&k, &v))
+ bincode::serde::encode_into_std_write(&(&k, &v), &mut self.scratch, BINCODE_CONFIG)
.map_err(serialize_err)?;
self.flush_scratch()?;
let prev = self.map.insert(k, v);
@@ -246,10 +262,9 @@
if !self.map.contains_key(k) {
return Ok(None);
}
- self.scratch.clear();
- self.scratch.extend_from_slice(&[0u8; LEN_BYTES]);
+ self.scratch.truncate(LEN_BYTES);
self.scratch.push(TAG_REMOVE);
- bincode::serialize_into(&mut self.scratch, k)
+ bincode::serde::encode_into_std_write(k, &mut self.scratch, BINCODE_CONFIG)
.map_err(serialize_err)?;
self.flush_scratch()?;
let prev = self.map.shift_remove(k);
@@ -276,10 +291,9 @@
let result = f(v_mut);
let v_ref: &V = v_mut;
- self.scratch.clear();
- self.scratch.extend_from_slice(&[0u8; LEN_BYTES]);
+ self.scratch.truncate(LEN_BYTES);
self.scratch.push(TAG_INSERT);
- bincode::serialize_into(&mut self.scratch, &(k, v_ref))
+ bincode::serde::encode_into_std_write(&(k, v_ref), &mut self.scratch, BINCODE_CONFIG)
.map_err(serialize_err)?;
self.flush_scratch()?;
@@ -307,13 +321,15 @@
.write(true)
.open(&tmp_path)?;
let mut writer = BufWriter::with_capacity(self.cfg.buf_capacity, tmp);
- let mut buf = Vec::with_capacity(256);
+ let mut buf: Vec<u8> = Vec::with_capacity(256);
for (k, v) in &self.map {
buf.clear();
+ buf.extend_from_slice(&[0u8; LEN_BYTES]);
buf.push(TAG_INSERT);
- bincode::serialize_into(&mut buf, &(k, v))
+ bincode::serde::encode_into_std_write(&(k, v), &mut buf, BINCODE_CONFIG)
.map_err(serialize_err)?;
- writer.write_all(&(buf.len() as u32).to_le_bytes())?;
+ let payload_len = (buf.len() - LEN_BYTES) as u32;
+ buf[..LEN_BYTES].copy_from_slice(&payload_len.to_le_bytes());
writer.write_all(&buf)?;
}
writer.flush()?;
@@ -333,7 +349,7 @@
Ok(())
}
- #[inline]
+ #[inline(always)]
fn flush_scratch(&mut self) -> io::Result<()> {
// Callers reserve LEN_BYTES at the front of `scratch`; fill the length
// in place so the length-prefix and payload land in a single write.
@@ -371,6 +387,6 @@
}
#[inline]
-fn serialize_err(e: bincode::Error) -> io::Error {
+fn serialize_err(e: bincode::error::EncodeError) -> io::Error {
io::Error::new(ErrorKind::InvalidData, e)
}
@@ -8,7 +8,7 @@
[dependencies]
indexmap = { version = "2", features = ["serde"] }
serde = { version = "1", features = ["derive"] }
-bincode = "1.3"
+bincode = { version = "2.0.1", features = ["serde"] }
[dev-dependencies]
tempfile = "3"