use std::hint::black_box;
use criterion::{Criterion, criterion_group, criterion_main};
use intern_lang::{Interner, Symbol};
use token_lang::{Span, Token, TokenKind};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
enum Kind {
Ident(Symbol),
Plus,
Whitespace,
Eof,
}
impl TokenKind for Kind {
fn is_trivia(&self) -> bool {
matches!(self, Kind::Whitespace)
}
fn is_eof(&self) -> bool {
matches!(self, Kind::Eof)
}
fn symbol(&self) -> Option<Symbol> {
match self {
Kind::Ident(s) => Some(*s),
_ => None,
}
}
}
fn stream(n: usize) -> Vec<Token<Kind>> {
let mut interner = Interner::new();
let mut tokens = Vec::with_capacity(n * 4 + 1);
let mut at = 0u32;
for i in 0..n {
let sym = interner.intern(&format!("ident_{i}"));
tokens.push(Token::new(Kind::Ident(sym), Span::new(at, at + 5)));
tokens.push(Token::new(Kind::Whitespace, Span::new(at + 5, at + 6)));
tokens.push(Token::new(Kind::Plus, Span::new(at + 6, at + 7)));
tokens.push(Token::new(Kind::Whitespace, Span::new(at + 7, at + 8)));
at += 8;
}
tokens.push(Token::new(Kind::Eof, Span::empty(at)));
tokens
}
fn bench_filter_trivia(c: &mut Criterion) {
let tokens = stream(1_024);
c.bench_function("filter_trivia/1024", |b| {
b.iter(|| {
let count = tokens
.iter()
.filter(|t| !t.is_trivia() && !t.is_eof())
.count();
black_box(count)
});
});
}
fn bench_collect_symbols(c: &mut Criterion) {
let tokens = stream(1_024);
c.bench_function("collect_symbols/1024", |b| {
b.iter(|| {
let mut last = None;
for t in &tokens {
if let Some(sym) = t.symbol() {
last = Some(black_box(sym));
}
}
black_box(last)
});
});
}
fn bench_sort_into_source_order(c: &mut Criterion) {
let mut shuffled = stream(1_024);
shuffled.reverse();
c.bench_function("sort_source_order/1024", |b| {
b.iter_batched(
|| shuffled.clone(),
|mut tokens| {
tokens.sort();
black_box(tokens)
},
criterion::BatchSize::SmallInput,
);
});
}
criterion_group!(
benches,
bench_filter_trivia,
bench_collect_symbols,
bench_sort_into_source_order
);
criterion_main!(benches);