Skip to content

Commit

Permalink
Add zstd time column to benchmark. (#67)
Browse files Browse the repository at this point in the history
* Add zstd time column to benchmark.

* fmt

* Update README.md.template

* Use zstd_time in interactive site.
  • Loading branch information
caibear authored Mar 16, 2024
1 parent d5f9a37 commit 9c45d34
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 19 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ bebop = { version = "2.4.9", optional = true }
bincode1 = { package = "bincode", version = "1.3.3", optional = true }
# Can't call it bincode2 because of a current issue of bincode2
bincode = { package = "bincode", version = "2.0.0-rc", optional = true }
bitcode = { version = "0.6.0-alpha.2", optional = true }
bitcode = { version = "=0.6.0-alpha.2", optional = true }
borsh = { version = "1.1.1", features = ["derive"], optional = true }
# TODO: Unfork after bson adds support for pre-warmed serialization buffers
# https://github.com/mongodb/bson-rust/pull/328
Expand Down
17 changes: 11 additions & 6 deletions pages/src/calc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,26 @@ pub fn calc(
let Row {
feature,
serialize,
sizes,
compression,
..
} = r;
let uncompressed_size = *sizes.get(Compression::None).unwrap();
let uncompressed_size = compression.get(Compression::None).unwrap().size;

sizes
compression
.into_iter()
.filter(|(c, _)| compression_set.contains(*c))
.map(move |(compression, compressed_size)| {
.map(move |(compression, entry)| {
let compressed_size = entry.size;
let compress_time = entry.compress.map(|v| v as f32);

// TODO this assumes that inbound bandwidth is equivalent to outbound bandwidth which isn't the case for many VPS.
let limit_size = bandwidth_per_second
/ (compressed_size * if mode == Mode::RoundTrip { 2 } else { 1 }) as f32;

let serialize_seconds =
serialize + compression.serialize_seconds(uncompressed_size);
// Use measured compress_time if it exists, or estimate it with Compression::serialize_seconds.
let serialize_seconds = serialize
+ compress_time
.unwrap_or_else(|| compression.serialize_seconds(uncompressed_size));
let deserialize_seconds =
deserialize + compression.deserialize_seconds(uncompressed_size);
let limit_speed = cpus
Expand Down
36 changes: 30 additions & 6 deletions pages/src/row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ pub struct Row {
pub feature: String,
pub serialize: f32,
pub deserialize: Option<f32>,
pub sizes: CompressionMap<u64>,
pub compression: CompressionMap<CompressionEntry>,
}

#[derive(Debug)]
pub struct CompressionEntry {
pub size: u64,
pub compress: Option<f64>,
}

type Error = &'static str;
Expand Down Expand Up @@ -38,16 +44,34 @@ impl TryFrom<(&String, &Feature)> for Row {
.and_then(|v| unwrap_seconds(v).ok().flatten())
.map(|v| v as f32);

let mut sizes = CompressionMap::default();
sizes.insert(Compression::None, unwrap_bytes(col("size")?)?);
sizes.insert(Compression::Zlib, unwrap_bytes(col("zlib")?)?);
sizes.insert(Compression::Zstd, unwrap_bytes(col("zstd")?)?);
let mut compression = CompressionMap::default();
compression.insert(
Compression::None,
CompressionEntry {
size: unwrap_bytes(col("size")?)?,
compress: None,
},
);
compression.insert(
Compression::Zlib,
CompressionEntry {
size: unwrap_bytes(col("zlib")?)?,
compress: None,
},
);
compression.insert(
Compression::Zstd,
CompressionEntry {
size: unwrap_bytes(col("zstd")?)?,
compress: unwrap_seconds(col("zstd_time")?)?,
},
);

Ok(Self {
feature: feature.clone(),
serialize,
deserialize,
sizes,
compression,
})
}
}
19 changes: 19 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,25 @@ pub fn bench_size(name: &str, lib: &str, bytes: &[u8]) {
println!("{}/{}/size {}", name, lib, bytes.len());
println!("{}/{}/zlib {}", name, lib, zlib_size(bytes));
println!("{}/{}/zstd {}", name, lib, zstd_size(bytes));
println!(
"{}/{}/zstd_time {}",
name,
lib,
bench_compression(|| zstd_size(bytes))
);
}

fn bench_compression(compress: impl Fn() -> usize) -> String {
let start = std::time::Instant::now();
let size = compress();
let elapsed = start.elapsed();

let s = format!("{elapsed:.4?}");
let (number, unit): (String, String) = s.chars().partition(|c| c.is_numeric() || *c == '.');
let s = format!("{number} {unit}");

let mb_per_second = ((size as f64 / 1_000_000.0) / elapsed.as_secs_f64()) as u64;
format!("time: [{s} {s} {s}] {mb_per_second} MB/s")
}

fn zlib_size(mut bytes: &[u8]) -> usize {
Expand Down
2 changes: 2 additions & 0 deletions tools/README.md.template
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ All tests benchmark the following properties (time or size):
* **Deserialize**: deserializes a buffer into a normal rust object
* **Size**: the size of the buffer when serialized
* **Zlib**: the size of the buffer after zlib compression
* **Zstd**: the size of the buffer after zstd compression
* **Zstd Time**: the time taken to compress the serialized buffer with zstd

Zero-copy deserialization libraries have an additional set of benchmarks:

Expand Down
24 changes: 18 additions & 6 deletions tools/formatter/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,16 @@ fn write_crate_row(output: &mut String, feature: &str, features: &Features) -> f
}

pub fn capitalize(s: &str) -> String {
let mut c = s.chars();
match c.next() {
None => String::new(),
Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
}
s.split("_")
.map(|s| {
let mut c = s.chars();
match c.next() {
None => String::new(),
Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
}
})
.collect::<Vec<_>>()
.join(" ")
}

fn build_tables(
Expand Down Expand Up @@ -189,7 +194,14 @@ fn format(
template: &str,
date: &str,
) -> Result<String, fmt::Error> {
const SERDE_COLS: &[&str] = &["serialize", "deserialize", "size", "zlib", "zstd"];
const SERDE_COLS: &[&str] = &[
"serialize",
"deserialize",
"size",
"zlib",
"zstd",
"zstd_time",
];
const ZCD_COLS: &[&str] = &["access", "read", "update"];

let mut tables = String::new();
Expand Down

0 comments on commit 9c45d34

Please sign in to comment.