I needed a const evaluation of fastnum (which is really cool!) so I have replaced rust_decimal with fastnum in my project. Unfortunately, my app started using ~20% of CPU vs ~3% with rust_decimal before.
I have written a simple benchmark comparison of fastnum vs rust_decimal with the most used operations from my app and this is the output:
String parsing: Fastnum 222.69ms vs Rust Decimal 105.50ms (2.11x slower)
Addition: Fastnum 25.50ms vs Rust Decimal 9.08ms (2.81x slower)
Subtraction: Fastnum 27.15ms vs Rust Decimal 9.63ms (2.82x slower)
Multiplication: Fastnum 35.88ms vs Rust Decimal 8.85ms (4.05x slower)
Division: Fastnum 1435.93ms vs Rust Decimal 71.45ms (20.10x slower)
I don't know the details of both lib's implementation but I would guess the parsing of str should take the same time. Also div operation taking 20x as much seems to me a lot. Could the performance be improved please?
#[cfg(test)]
mod benchmark {
use fastnum::{D128, dec128};
use rust_decimal::Decimal;
use std::str::FromStr;
use std::time::Instant;
#[test]
fn fastnum_vs_rust_decimal_benchmark() {
let iterations = 1_000_000;
let a_fn = dec128!(789.012);
let b_fn = dec128!(12.345);
let a_rd = Decimal::from_str("789.012").unwrap();
let b_rd = Decimal::from_str("12.345").unwrap();
// String parsing
let test_strings = vec!["123.456", "0.05", "-0.05", "1000000.123456789", "0.000001"];
let start = Instant::now();
for _ in 0..iterations {
for s in &test_strings {
let _res: D128 = s.parse().unwrap();
}
}
let fastnum_str = start.elapsed();
let start = Instant::now();
for _ in 0..iterations {
for s in &test_strings {
let _res: Decimal = Decimal::from_str(s).unwrap();
}
}
let rust_decimal_str = start.elapsed();
// Addition
let start = Instant::now();
for _ in 0..iterations {
let _res = a_fn + b_fn;
}
let fastnum_add = start.elapsed();
let start = Instant::now();
for _ in 0..iterations {
let _res = a_rd + b_rd;
}
let rust_decimal_add = start.elapsed();
// Subtraction
let start = Instant::now();
for _ in 0..iterations {
let _res = a_fn - b_fn;
}
let fastnum_sub = start.elapsed();
let start = Instant::now();
for _ in 0..iterations {
let _res = a_rd - b_rd;
}
let rust_decimal_sub = start.elapsed();
// Multiplication
let start = Instant::now();
for _ in 0..iterations {
let _res = a_fn * b_fn;
}
let fastnum_mul = start.elapsed();
let start = Instant::now();
for _ in 0..iterations {
let _res = a_rd * b_rd;
}
let rust_decimal_mul = start.elapsed();
// Division
let start = Instant::now();
for _ in 0..iterations {
let _res = a_fn / b_fn;
}
let fastnum_div = start.elapsed();
let start = Instant::now();
for _ in 0..iterations {
let _res = a_rd / b_rd;
}
let rust_decimal_div = start.elapsed();
println!("=== Fastnum D128 vs Rust Decimal Performance ===");
println!(
"String parsing: Fastnum {:.2}ms vs Rust Decimal {:.2}ms ({:.2}x slower)",
fastnum_str.as_nanos() as f64 / 1_000_000.0,
rust_decimal_str.as_nanos() as f64 / 1_000_000.0,
fastnum_str.as_nanos() as f64 / rust_decimal_str.as_nanos() as f64
);
println!(
"Addition: Fastnum {:.2}ms vs Rust Decimal {:.2}ms ({:.2}x slower)",
fastnum_add.as_nanos() as f64 / 1_000_000.0,
rust_decimal_add.as_nanos() as f64 / 1_000_000.0,
fastnum_add.as_nanos() as f64 / rust_decimal_add.as_nanos() as f64
);
println!(
"Subtraction: Fastnum {:.2}ms vs Rust Decimal {:.2}ms ({:.2}x slower)",
fastnum_sub.as_nanos() as f64 / 1_000_000.0,
rust_decimal_sub.as_nanos() as f64 / 1_000_000.0,
fastnum_sub.as_nanos() as f64 / rust_decimal_sub.as_nanos() as f64
);
println!(
"Multiplication: Fastnum {:.2}ms vs Rust Decimal {:.2}ms ({:.2}x slower)",
fastnum_mul.as_nanos() as f64 / 1_000_000.0,
rust_decimal_mul.as_nanos() as f64 / 1_000_000.0,
fastnum_mul.as_nanos() as f64 / rust_decimal_mul.as_nanos() as f64
);
println!(
"Division: Fastnum {:.2}ms vs Rust Decimal {:.2}ms ({:.2}x slower)",
fastnum_div.as_nanos() as f64 / 1_000_000.0,
rust_decimal_div.as_nanos() as f64 / 1_000_000.0,
fastnum_div.as_nanos() as f64 / rust_decimal_div.as_nanos() as f64
);
}
}
related #12
I needed a const evaluation of
fastnum(which is really cool!) so I have replacedrust_decimalwithfastnumin my project. Unfortunately, my app started using ~20% of CPU vs ~3% withrust_decimalbefore.I have written a simple benchmark comparison of fastnum vs rust_decimal with the most used operations from my app and this is the output:
I don't know the details of both lib's implementation but I would guess the parsing of str should take the same time. Also div operation taking 20x as much seems to me a lot. Could the performance be improved please?
related #12