Skip to main content

bench/
bench.rs

1use std::hint::{black_box, spin_loop};
2use std::thread;
3use std::time::Instant;
4
5use polymarket_kernel::calculate_quotes_logit;
6use polymarket_kernel::ring_buffer::{L2Update, SpscRingBuffer, split};
7
8const MARKETS: usize = 8_192;
9const QUOTE_ITERS: usize = 100_000;
10
11const SPSC_CAPACITY: usize = 1 << 20; // 1,048,576
12const SPSC_MESSAGES: u64 = 10_000_000;
13
14fn bench_quote_latency() -> f64 {
15    let mut x_t = vec![0.0_f64; MARKETS];
16    let mut q_t = vec![0.0_f64; MARKETS];
17    let mut sigma_b = vec![0.0_f64; MARKETS];
18    let mut gamma = vec![0.0_f64; MARKETS];
19    let mut tau = vec![0.0_f64; MARKETS];
20    let mut k = vec![0.0_f64; MARKETS];
21
22    let mut bid_p = vec![0.0_f64; MARKETS];
23    let mut ask_p = vec![0.0_f64; MARKETS];
24
25    for i in 0..MARKETS {
26        let fi = i as f64;
27        x_t[i] = ((fi % 1000.0) / 1000.0 - 0.5) * 4.0; // [-2, 2]
28        q_t[i] = (i as i64 % 41 - 20) as f64; // inventory in [-20, 20]
29        sigma_b[i] = 0.10 + ((i % 200) as f64) * 0.0015; // [0.10, 0.3985]
30        gamma[i] = 0.03 + ((i % 7) as f64) * 0.01; // [0.03, 0.09]
31        tau[i] = 0.05 + ((i % 365) as f64) / 365.0; // [0.05, ~1.05]
32        k[i] = 1.0 + ((i % 50) as f64) * 0.08; // [1.0, 4.92]
33    }
34
35    for _ in 0..2_000 {
36        calculate_quotes_logit(
37            &x_t, &q_t, &sigma_b, &gamma, &tau, &k, &mut bid_p, &mut ask_p,
38        );
39    }
40
41    let start = Instant::now();
42    for _ in 0..QUOTE_ITERS {
43        calculate_quotes_logit(
44            black_box(&x_t),
45            black_box(&q_t),
46            black_box(&sigma_b),
47            black_box(&gamma),
48            black_box(&tau),
49            black_box(&k),
50            black_box(&mut bid_p),
51            black_box(&mut ask_p),
52        );
53    }
54    let elapsed = start.elapsed();
55
56    let total_updates = (MARKETS as u128) * (QUOTE_ITERS as u128);
57    let ns_per_market = elapsed.as_nanos() as f64 / total_updates as f64;
58
59    black_box((&bid_p, &ask_p));
60    ns_per_market
61}
62
63fn bench_spsc_throughput() -> f64 {
64    let mut ring = SpscRingBuffer::default();
65    let mut slots = vec![L2Update::default(); SPSC_CAPACITY];
66
67    let (mut producer, mut consumer) =
68        split(&mut ring, &mut slots).expect("failed to initialize SPSC ring buffer");
69
70    let start = Instant::now();
71
72    thread::scope(|scope| {
73        let producer_handle = scope.spawn(move || {
74            for i in 0..SPSC_MESSAGES {
75                let mut msg = L2Update {
76                    market_id: i & 0x1fff,
77                    mid_price: 0.45 + ((i % 10_000) as f64) * 0.00001,
78                    implied_vol: 0.08 + ((i % 1_000) as f64) * 0.0001,
79                };
80
81                loop {
82                    match producer.try_push(msg) {
83                        Ok(()) => break,
84                        Err(m) => {
85                            msg = m;
86                            spin_loop();
87                        }
88                    }
89                }
90            }
91        });
92
93        let consumer_handle = scope.spawn(move || {
94            let mut received = 0_u64;
95            let mut checksum = 0.0_f64;
96
97            while received < SPSC_MESSAGES {
98                if let Some(msg) = consumer.try_pop() {
99                    received += 1;
100                    checksum += msg.mid_price + msg.implied_vol + (msg.market_id as f64) * 1e-12;
101                } else {
102                    spin_loop();
103                }
104            }
105
106            black_box(checksum);
107            received
108        });
109
110        producer_handle
111            .join()
112            .expect("producer thread panicked during benchmark");
113
114        let received = consumer_handle
115            .join()
116            .expect("consumer thread panicked during benchmark");
117        assert_eq!(received, SPSC_MESSAGES, "message loss in SPSC benchmark");
118    });
119
120    let elapsed = start.elapsed();
121    let secs = elapsed.as_secs_f64();
122    (SPSC_MESSAGES as f64 / 1_000_000.0) / secs
123}
124
125fn main() {
126    println!("============================================================");
127    println!(" POLYMARKET-KERNEL RAW BENCHMARK ");
128    println!("============================================================");
129    println!(" Quote Batch Size        : {:>10} markets", MARKETS);
130    println!(" Quote Iterations        : {:>10}", QUOTE_ITERS);
131
132    let ns_per_market = bench_quote_latency();
133    println!(
134        " Runtime-Dispatch Quote : {:>10.2} ns/market",
135        ns_per_market
136    );
137
138    println!("------------------------------------------------------------");
139    println!(" SPSC Ring Capacity      : {:>10}", SPSC_CAPACITY);
140    println!(" SPSC Messages           : {:>10}", SPSC_MESSAGES);
141
142    let mops = bench_spsc_throughput();
143    println!(" SPSC Throughput         : {:>10.2} M msgs/sec", mops);
144    println!("============================================================");
145}