diff --git a/sje/Cargo.toml b/sje/Cargo.toml index b6c6453..c6f7a0a 100644 --- a/sje/Cargo.toml +++ b/sje/Cargo.toml @@ -21,6 +21,7 @@ sje_derive = { path = "../sje_derive" } criterion = "0.5.1" serde = { version = "1.0.217", features = ["derive"] } serde_json = "1.0.138" +sonic-rs = "0.3" [features] default = [] diff --git a/sje/benches/l2_update.rs b/sje/benches/l2_update.rs index 51a8360..065792d 100644 --- a/sje/benches/l2_update.rs +++ b/sje/benches/l2_update.rs @@ -1,8 +1,8 @@ use criterion::{Criterion, Throughput, criterion_group, criterion_main}; use serde::{Deserialize, Deserializer}; use sje_derive::Decoder; +use sonic_rs::{from_slice, from_slice_unchecked}; use std::str::FromStr; - const JSON: &[u8] = br#"{"e":"depthUpdate","E":1739836781765,"T":1739836781757,"s":"XRPUSDT","U":6780157664288,"u":6780157666166,"pu":6780157664112,"b":[["2.6461","6404.9"],["2.6468","22540.8"]],"a":[["2.6582","12708.6"],["2.6588","10898.1"],["2.6611","16595.4"]]}"#; #[derive(Debug, Copy, Clone, PartialEq)] @@ -140,5 +140,69 @@ fn serde_l2_update_benchmark(c: &mut Criterion) { }); } -criterion_group!(benches, sje_l2_update_benchmark, serde_l2_update_benchmark); +fn sonic_l2_update_benchmark(c: &mut Criterion) { + let mut group = c.benchmark_group("sonic_safe"); + group.throughput(Throughput::Elements(1)); + group.throughput(Throughput::Bytes(JSON.len() as u64)); + + group.bench_function("sonic_l2_update", |b| { + b.iter(|| { + let l2_update: L2Update = from_slice(JSON).unwrap(); + + assert_eq!("depthUpdate", l2_update.event_type); + assert_eq!(1739836781765, l2_update.event_time); + assert_eq!(1739836781757, l2_update.transaction_time); + assert_eq!("XRPUSDT", l2_update.symbol); + assert_eq!(6780157664288, l2_update.first_update_id); + assert_eq!(6780157666166, l2_update.final_update_id); + assert_eq!(6780157664112, l2_update.previous_final_update_id); + + let mut bids = l2_update.bids.into_iter(); + assert_eq!((Price(2.6461), Quantity(6404.9)), bids.next().unwrap()); + assert_eq!((Price(2.6468), Quantity(22540.8)), bids.next().unwrap()); + + let mut asks = l2_update.asks.into_iter(); + assert_eq!((Price(2.6582), Quantity(12708.6)), asks.next().unwrap()); + assert_eq!((Price(2.6588), Quantity(10898.1)), asks.next().unwrap()); + assert_eq!((Price(2.6611), Quantity(16595.4)), asks.next().unwrap()); + }) + }); +} + +fn sonic_unchecked_l2_update_benchmark(c: &mut Criterion) { + let mut group = c.benchmark_group("sonic_unsafe"); + group.throughput(Throughput::Elements(1)); + group.throughput(Throughput::Bytes(JSON.len() as u64)); + + group.bench_function("sonic_l2_update", |b| { + b.iter(|| { + let l2_update: L2Update = unsafe { from_slice_unchecked(JSON).unwrap() }; + + assert_eq!("depthUpdate", l2_update.event_type); + assert_eq!(1739836781765, l2_update.event_time); + assert_eq!(1739836781757, l2_update.transaction_time); + assert_eq!("XRPUSDT", l2_update.symbol); + assert_eq!(6780157664288, l2_update.first_update_id); + assert_eq!(6780157666166, l2_update.final_update_id); + assert_eq!(6780157664112, l2_update.previous_final_update_id); + + let mut bids = l2_update.bids.into_iter(); + assert_eq!((Price(2.6461), Quantity(6404.9)), bids.next().unwrap()); + assert_eq!((Price(2.6468), Quantity(22540.8)), bids.next().unwrap()); + + let mut asks = l2_update.asks.into_iter(); + assert_eq!((Price(2.6582), Quantity(12708.6)), asks.next().unwrap()); + assert_eq!((Price(2.6588), Quantity(10898.1)), asks.next().unwrap()); + assert_eq!((Price(2.6611), Quantity(16595.4)), asks.next().unwrap()); + }) + }); +} + +criterion_group!( + benches, + sje_l2_update_benchmark, + serde_l2_update_benchmark, + sonic_l2_update_benchmark, + sonic_unchecked_l2_update_benchmark +); criterion_main!(benches); diff --git a/sje/benches/ticker.rs b/sje/benches/ticker.rs index adcf7a2..745729c 100644 --- a/sje/benches/ticker.rs +++ b/sje/benches/ticker.rs @@ -1,6 +1,7 @@ use criterion::{Criterion, Throughput, criterion_group, criterion_main}; use serde::Deserialize; use sje_derive::Decoder; +use sonic_rs::{from_slice, from_slice_unchecked}; const JSON: &[u8] = br#"{"e":"bookTicker","u":6780157666962,"s":"BTCUSDT","b":"95732.60","B":"2.073","a":"95732.70","A":"23.383","T":1739836781773,"E":1739836781774}"#; @@ -79,5 +80,53 @@ fn serde_ticker_benchmark(c: &mut Criterion) { }); } -criterion_group!(benches, sje_ticker_benchmark, serde_ticker_benchmark); +fn sonic_ticker_benchmark(c: &mut Criterion) { + let mut group = c.benchmark_group("sonic_safe"); + group.throughput(Throughput::Elements(1)); + group.throughput(Throughput::Bytes(JSON.len() as u64)); + + group.bench_function("sonic_ticker", |b| { + b.iter(|| { + let ticker: Ticker = from_slice(JSON).unwrap(); + assert_eq!("bookTicker", ticker.event_type); + assert_eq!(6780157666962, ticker.update_id); + assert_eq!("BTCUSDT", ticker.symbol); + assert_eq!("95732.60", ticker.bid_price); + assert_eq!("2.073", ticker.bid_qty); + assert_eq!("95732.70", ticker.ask_price); + assert_eq!("23.383", ticker.ask_qty); + assert_eq!(1739836781773, ticker.transaction_time); + assert_eq!(1739836781774, ticker.event_time); + }) + }); +} + +fn sonic_unchecked_ticker_benchmark(c: &mut Criterion) { + let mut group = c.benchmark_group("sonic_unsafe"); + group.throughput(Throughput::Elements(1)); + group.throughput(Throughput::Bytes(JSON.len() as u64)); + + group.bench_function("sonic_ticker", |b| { + b.iter(|| { + let ticker: Ticker = unsafe { from_slice_unchecked(JSON).unwrap() }; + assert_eq!("bookTicker", ticker.event_type); + assert_eq!(6780157666962, ticker.update_id); + assert_eq!("BTCUSDT", ticker.symbol); + assert_eq!("95732.60", ticker.bid_price); + assert_eq!("2.073", ticker.bid_qty); + assert_eq!("95732.70", ticker.ask_price); + assert_eq!("23.383", ticker.ask_qty); + assert_eq!(1739836781773, ticker.transaction_time); + assert_eq!(1739836781774, ticker.event_time); + }) + }); +} + +criterion_group!( + benches, + sje_ticker_benchmark, + serde_ticker_benchmark, + sonic_ticker_benchmark, + sonic_unchecked_ticker_benchmark +); criterion_main!(benches); diff --git a/sje/benches/trade.rs b/sje/benches/trade.rs index f6f9349..a038490 100644 --- a/sje/benches/trade.rs +++ b/sje/benches/trade.rs @@ -1,6 +1,7 @@ use criterion::{Criterion, Throughput, criterion_group, criterion_main}; use serde::Deserialize; use sje_derive::Decoder; +use sonic_rs::{from_slice, from_slice_unchecked}; const JSON: &[u8] = br#"{"e":"trade","E":1705085312569,"s":"BTCUSDT","t":3370034463,"p":"43520.00000000","q":"0.00022000","b":24269765071,"a":24269767699,"T":1705085312568,"m":true,"M":true}"#; @@ -84,5 +85,55 @@ fn serde_trade_benchmark(c: &mut Criterion) { }); } -criterion_group!(benches, sje_trade_benchmark, serde_trade_benchmark); +fn sonic_trade_benchmark(c: &mut Criterion) { + let mut group = c.benchmark_group("sonic_safe"); + group.throughput(Throughput::Elements(1)); + group.throughput(Throughput::Bytes(JSON.len() as u64)); + + group.bench_function("sonic_trade", |b| { + b.iter(|| { + let trade: Trade = from_slice(JSON).unwrap(); + assert_eq!("trade", trade.event_type); + assert_eq!(1705085312569, trade.event_time); + assert_eq!("BTCUSDT", trade.symbol); + assert_eq!(3370034463, trade.trade_id); + assert_eq!("43520.00000000", trade.price); + assert_eq!("0.00022000", trade.quantity); + assert_eq!(24269765071, trade.buyer_order_id); + assert_eq!(24269767699, trade.seller_order_id); + assert_eq!(1705085312568, trade.transaction_time); + assert!(trade.is_buyer_maker); + }) + }); +} + +fn sonic_unchecked_trade_benchmark(c: &mut Criterion) { + let mut group = c.benchmark_group("sonic_unsafe"); + group.throughput(Throughput::Elements(1)); + group.throughput(Throughput::Bytes(JSON.len() as u64)); + + group.bench_function("sonic_trade", |b| { + b.iter(|| { + let trade: Trade = unsafe { from_slice_unchecked(JSON).unwrap() }; + assert_eq!("trade", trade.event_type); + assert_eq!(1705085312569, trade.event_time); + assert_eq!("BTCUSDT", trade.symbol); + assert_eq!(3370034463, trade.trade_id); + assert_eq!("43520.00000000", trade.price); + assert_eq!("0.00022000", trade.quantity); + assert_eq!(24269765071, trade.buyer_order_id); + assert_eq!(24269767699, trade.seller_order_id); + assert_eq!(1705085312568, trade.transaction_time); + assert!(trade.is_buyer_maker); + }) + }); +} + +criterion_group!( + benches, + sje_trade_benchmark, + serde_trade_benchmark, + sonic_trade_benchmark, + sonic_unchecked_trade_benchmark +); criterion_main!(benches);