use cli_chat_core::types::{FixedString, Message};
use cli_chat_core::{AppState, SerialPort, Storage};
use criterion::{Criterion, criterion_group, criterion_main};
use std::hint::black_box;
struct BenchSerial;
impl SerialPort for BenchSerial {
#[inline]
fn write_byte(&mut self, byte: u8) {}
#[inline]
fn read_byte(&mut self) -> Option<u8> {
None
}
}
struct BenchStorage {
buf: [u8; 32768],
}
impl BenchStorage {
fn new() -> Self {
Self { buf: [0; 32768] }
}
}
impl Storage for BenchStorage {
#[inline]
fn read(&mut self, _offset: usize, _buffer: &mut [u8]) -> Result<usize, &'static str> {
Ok(0)
}
#[inline]
fn write(&mut self, offset: usize, buffer: &[u8]) -> Result<(), &'static str> {
let end = offset + buffer.len();
if end <= self.buf.len() {
self.buf[offset..end].copy_from_slice(buffer);
Ok(())
} else {
Err("Out of memory in BenchStorage")
}
}
#[inline]
fn flush(&mut self) -> Result<(), &'static str> {
Ok(())
}
}
fn bench_parse_latency(criterion: &mut Criterion) {
let mut state = AppState::uninit();
let mut port = BenchSerial;
let mut storage = BenchStorage::new();
state.init(&mut storage, &mut port).unwrap();
let input = b"Hello, this is a benchmark message!\r";
criterion.bench_function("parse_latency", |bench| {
bench.iter(|| {
for &byte in input {
state
.process_byte(black_box(byte), &mut port, &mut storage)
.unwrap();
}
});
});
}
fn bench_storage_serialize(criterion: &mut Criterion) {
let mut state = AppState::uninit();
let mut port = BenchSerial;
let mut storage = BenchStorage::new();
state.init(&mut storage, &mut port).unwrap();
for &byte in b"/user 1\r/name BenchUser\r" {
state.process_byte(byte, &mut port, &mut storage).unwrap();
}
criterion.bench_function("storage_serialize", |bench| {
bench.iter(|| {
state.flush(black_box(&mut storage)).unwrap();
});
});
}
fn bench_ansi_render(criterion: &mut Criterion) {
let mut state = AppState::uninit();
let mut port = BenchSerial;
let mut storage = BenchStorage::new();
state.init(&mut storage, &mut port).unwrap();
let msg = Message {
user_id: 1,
padding: 0,
tick: 100,
content: FixedString::new(),
};
criterion.bench_function("ansi_render", |bench| {
bench.iter(|| {
cli_chat_core::state::render::render_prompt(black_box(&state), &mut port);
cli_chat_core::state::render::render_message(
black_box(&state),
black_box(&msg),
&mut port,
);
});
});
}
criterion_group!(
benches,
bench_parse_latency,
bench_storage_serialize,
bench_ansi_render
);
criterion_main!(benches);