mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-07 16:36:58 +00:00
102 lines
3.3 KiB
Rust
102 lines
3.3 KiB
Rust
//! `cargo bench -p ide-text`: change sets and coordinate conversion on a 1 MB document.
|
|
|
|
use criterion::{BatchSize, Criterion, black_box, criterion_group, criterion_main};
|
|
use ide_core::{ChangeSet, Pos, TextChange};
|
|
use ide_text::Document;
|
|
|
|
/// ~1 MB of code-like text with some non-ASCII content.
|
|
fn sample_text() -> String {
|
|
let mut s = String::with_capacity(1 << 20);
|
|
let mut i = 0u32;
|
|
while s.len() < 1 << 20 {
|
|
s.push_str(&format!(" let value_{i} = compute(\"héllo 😀\", {i}) + other_{i};\n"));
|
|
i += 1;
|
|
}
|
|
s
|
|
}
|
|
|
|
struct Lcg(u64);
|
|
impl Lcg {
|
|
fn next(&mut self, n: u32) -> u32 {
|
|
self.0 = self.0.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
|
|
((self.0 >> 33) % n.max(1) as u64) as u32
|
|
}
|
|
}
|
|
|
|
fn change_set(doc: &Document, rng: &mut Lcg, n: usize) -> ChangeSet {
|
|
let len = doc.len_utf16();
|
|
let mut points: Vec<u32> = (0..n * 2).map(|_| rng.next(len)).collect();
|
|
points.sort_unstable();
|
|
// Snap to char boundaries so the set is valid.
|
|
let changes = points
|
|
.chunks(2)
|
|
.map(|p| {
|
|
let from = doc.pos_to_offset(doc.offset_to_pos(p[0]));
|
|
let to = doc.pos_to_offset(doc.offset_to_pos(p[1])).max(from);
|
|
TextChange { from, to: to.min(from + 8), insert: "x_y\n".into() }
|
|
})
|
|
.collect::<Vec<_>>();
|
|
// Keep the set sorted and non-overlapping after clamping.
|
|
let mut out: Vec<TextChange> = Vec::with_capacity(changes.len());
|
|
for c in changes {
|
|
if out.last().is_none_or(|l| c.from >= l.to) {
|
|
out.push(c);
|
|
}
|
|
}
|
|
ChangeSet { changes: out }
|
|
}
|
|
|
|
fn bench(c: &mut Criterion) {
|
|
let text = sample_text();
|
|
c.bench_function("text/open_1mb", |b| b.iter(|| Document::new(black_box(&text))));
|
|
|
|
let base = Document::new(&text);
|
|
c.bench_function("text/apply_keystroke_1mb", |b| {
|
|
let mut rng = Lcg(7);
|
|
b.iter_batched_ref(
|
|
|| {
|
|
let cs = change_set(&base, &mut rng, 1);
|
|
(base.clone(), cs)
|
|
},
|
|
|(doc, cs)| doc.apply_detailed(0, cs).unwrap(),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
c.bench_function("text/apply_100_changes_1mb", |b| {
|
|
let mut rng = Lcg(11);
|
|
b.iter_batched_ref(
|
|
|| {
|
|
let cs = change_set(&base, &mut rng, 100);
|
|
(base.clone(), cs)
|
|
},
|
|
|(doc, cs)| doc.apply_detailed(0, cs).unwrap(),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
c.bench_function("text/offset_to_pos_round_trip", |b| {
|
|
let mut rng = Lcg(3);
|
|
let len = base.len_utf16();
|
|
b.iter(|| {
|
|
let pos = base.offset_to_pos(rng.next(len));
|
|
black_box(base.pos_to_offset(pos))
|
|
})
|
|
});
|
|
c.bench_function("text/pos_to_byte", |b| {
|
|
let mut rng = Lcg(5);
|
|
let lines = base.line_count();
|
|
b.iter(|| black_box(base.pos_to_byte(Pos::new(rng.next(lines), rng.next(60)))))
|
|
});
|
|
c.bench_function("text/text_for_save_crlf_1mb", |b| {
|
|
let mut doc = base.clone();
|
|
doc.set_line_ending(ide_text::LineEnding::CrLf);
|
|
b.iter(|| black_box(doc.text_for_save().len()))
|
|
});
|
|
}
|
|
|
|
criterion_group! {
|
|
name = benches;
|
|
config = Criterion::default().sample_size(30).measurement_time(std::time::Duration::from_secs(3));
|
|
targets = bench
|
|
}
|
|
criterion_main!(benches);
|