Follow-up to https://github.com/zed-industries/zed/pull/62478#discussion_r3769810809 New bench results: | corpus | old | new | speedup | |---|---|---|---| | ascii, no invisibles | 83 MB/s | 580 MB/s | **7.0x** | | unicode, no invisibles | 88 MB/s | 442 MB/s | **5.0x** | | sparse invisibles | 63 MB/s | 431 MB/s | **6.9x** | | dense invisibles | 82 MB/s | 109 MB/s | 1.3x | Release Notes: - N/A
292 lines
9.5 KiB
Rust
292 lines
9.5 KiB
Rust
use criterion::{BenchmarkId, Criterion, black_box, criterion_group, criterion_main};
|
|
use editor::{EditorStyle, MultiBuffer, display_map::*};
|
|
use gpui::{AppContext as _, HighlightStyle, Hsla, TestDispatcher, font, px};
|
|
use itertools::Itertools;
|
|
use multi_buffer::MultiBufferOffset;
|
|
use project::project_settings::DiagnosticSeverity;
|
|
use rand::{Rng, SeedableRng, rngs::StdRng};
|
|
use settings::SettingsStore;
|
|
use std::{num::NonZeroU32, time::Duration};
|
|
use text::Bias;
|
|
use util::RandomCharIter;
|
|
|
|
fn to_tab_point_benchmark(c: &mut Criterion) {
|
|
let dispatcher = TestDispatcher::new(1);
|
|
let cx = gpui::TestAppContext::build(dispatcher, None);
|
|
|
|
let create_tab_map = |length: usize| {
|
|
let mut rng = StdRng::seed_from_u64(1);
|
|
let text = RandomCharIter::new(&mut rng)
|
|
.take(length)
|
|
.collect::<String>();
|
|
let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
|
|
|
|
let buffer_snapshot = cx.read(|cx| buffer.read(cx).snapshot(cx));
|
|
use editor::display_map::*;
|
|
let (_, inlay_snapshot) = InlayMap::new(buffer_snapshot);
|
|
let (_, fold_snapshot) = FoldMap::new(inlay_snapshot.clone());
|
|
let fold_point = fold_snapshot.to_fold_point(
|
|
inlay_snapshot.to_point(InlayOffset(
|
|
rng.random_range(MultiBufferOffset(0)..MultiBufferOffset(length)),
|
|
)),
|
|
Bias::Left,
|
|
);
|
|
let (_, snapshot) = TabMap::new(fold_snapshot, NonZeroU32::new(4).unwrap());
|
|
|
|
(length, snapshot, fold_point)
|
|
};
|
|
|
|
let inputs = [1024].into_iter().map(create_tab_map).collect_vec();
|
|
|
|
let mut group = c.benchmark_group("To tab point");
|
|
|
|
for (batch_size, snapshot, fold_point) in inputs {
|
|
group.bench_with_input(
|
|
BenchmarkId::new("to_tab_point", batch_size),
|
|
&snapshot,
|
|
|bench, snapshot| {
|
|
bench.iter(|| {
|
|
snapshot.fold_point_to_tab_point(fold_point);
|
|
});
|
|
},
|
|
);
|
|
}
|
|
|
|
group.finish();
|
|
}
|
|
|
|
fn to_fold_point_benchmark(c: &mut Criterion) {
|
|
let dispatcher = TestDispatcher::new(1);
|
|
let cx = gpui::TestAppContext::build(dispatcher, None);
|
|
|
|
let create_tab_map = |length: usize| {
|
|
let mut rng = StdRng::seed_from_u64(1);
|
|
let text = RandomCharIter::new(&mut rng)
|
|
.take(length)
|
|
.collect::<String>();
|
|
let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
|
|
|
|
let buffer_snapshot = cx.read(|cx| buffer.read(cx).snapshot(cx));
|
|
use editor::display_map::*;
|
|
let (_, inlay_snapshot) = InlayMap::new(buffer_snapshot);
|
|
let (_, fold_snapshot) = FoldMap::new(inlay_snapshot.clone());
|
|
|
|
let fold_point = fold_snapshot.to_fold_point(
|
|
inlay_snapshot.to_point(InlayOffset(
|
|
rng.random_range(MultiBufferOffset(0)..MultiBufferOffset(length)),
|
|
)),
|
|
Bias::Left,
|
|
);
|
|
|
|
let (_, snapshot) = TabMap::new(fold_snapshot, NonZeroU32::new(4).unwrap());
|
|
let tab_point = snapshot.fold_point_to_tab_point(fold_point);
|
|
|
|
(length, snapshot, tab_point)
|
|
};
|
|
|
|
let inputs = [1024].into_iter().map(create_tab_map).collect_vec();
|
|
|
|
let mut group = c.benchmark_group("To fold point");
|
|
|
|
for (batch_size, snapshot, tab_point) in inputs {
|
|
group.bench_with_input(
|
|
BenchmarkId::new("to_fold_point", batch_size),
|
|
&snapshot,
|
|
|bench, snapshot| {
|
|
bench.iter(|| {
|
|
snapshot.tab_point_to_fold_point(tab_point, Bias::Left);
|
|
});
|
|
},
|
|
);
|
|
}
|
|
|
|
group.finish();
|
|
}
|
|
|
|
fn create_highlight_endpoints_benchmark(c: &mut Criterion) {
|
|
const LINE_COUNT: usize = 20_000;
|
|
const LINE_VIEW_PORT_COUNT: usize = 100;
|
|
const HIGHLIGHTS_PER_LINE: usize = 4;
|
|
|
|
let dispatcher = TestDispatcher::new(1);
|
|
let mut cx = gpui::TestAppContext::build(dispatcher, None);
|
|
cx.update(|cx| {
|
|
let store = SettingsStore::test(cx);
|
|
cx.set_global(store);
|
|
editor::init(cx);
|
|
});
|
|
|
|
let mut text = String::new();
|
|
let mut highlight_ranges = Vec::with_capacity(LINE_COUNT * HIGHLIGHTS_PER_LINE);
|
|
for line in 0..LINE_COUNT {
|
|
text.push_str("fn item_");
|
|
text.push_str(&format!("{line:05}"));
|
|
text.push_str("() { ");
|
|
|
|
let start = text.len();
|
|
text.push_str("alpha_highlight");
|
|
highlight_ranges.push(MultiBufferOffset(start)..MultiBufferOffset(text.len()));
|
|
|
|
text.push_str(" + ");
|
|
let start = text.len();
|
|
text.push_str("beta_highlight");
|
|
highlight_ranges.push(MultiBufferOffset(start)..MultiBufferOffset(text.len()));
|
|
|
|
text.push_str(" + ");
|
|
let start = text.len();
|
|
text.push_str("gamma_highlight");
|
|
highlight_ranges.push(MultiBufferOffset(start)..MultiBufferOffset(text.len()));
|
|
|
|
text.push_str(" + ");
|
|
let start = text.len();
|
|
text.push_str("delta_highlight");
|
|
highlight_ranges.push(MultiBufferOffset(start)..MultiBufferOffset(text.len()));
|
|
|
|
text.push_str("; }\n");
|
|
}
|
|
|
|
let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
|
|
let buffer_snapshot = cx.read(|cx| buffer.read(cx).snapshot(cx));
|
|
let highlight_ranges = highlight_ranges
|
|
.into_iter()
|
|
.map(|range| {
|
|
buffer_snapshot.anchor_before(range.start)..buffer_snapshot.anchor_before(range.end)
|
|
})
|
|
.collect();
|
|
|
|
let map = cx.new(|cx| {
|
|
DisplayMap::new(
|
|
buffer,
|
|
font("Courier"),
|
|
px(16.0),
|
|
None,
|
|
1,
|
|
1,
|
|
FoldPlaceholder::default(),
|
|
DiagnosticSeverity::Warning,
|
|
cx,
|
|
)
|
|
});
|
|
cx.update(|cx| {
|
|
map.update(cx, |map, cx| {
|
|
map.highlight_text(
|
|
HighlightKey::Editor,
|
|
highlight_ranges,
|
|
HighlightStyle {
|
|
color: Some(Hsla::blue()),
|
|
..Default::default()
|
|
},
|
|
false,
|
|
cx,
|
|
);
|
|
});
|
|
});
|
|
let snapshot = cx.update(|cx| map.update(cx, |map, cx| map.snapshot(cx)));
|
|
|
|
let mut group = c.benchmark_group("Create highlight endpoints");
|
|
group.sample_size(10);
|
|
group.measurement_time(Duration::from_secs(10));
|
|
group.bench_with_input(
|
|
BenchmarkId::new("text_highlights", LINE_VIEW_PORT_COUNT),
|
|
&snapshot,
|
|
|bench, snapshot| {
|
|
bench.iter(|| {
|
|
black_box(snapshot.chunks(
|
|
DisplayRow(400)..DisplayRow(400 + LINE_VIEW_PORT_COUNT as u32),
|
|
language::LanguageAwareStyling {
|
|
tree_sitter: false,
|
|
diagnostics: false,
|
|
},
|
|
Default::default(),
|
|
));
|
|
});
|
|
},
|
|
);
|
|
group.finish();
|
|
}
|
|
|
|
fn highlighted_chunks_benchmark(c: &mut Criterion) {
|
|
const LINE_COUNT: usize = 500;
|
|
|
|
let dispatcher = TestDispatcher::new(1);
|
|
let mut cx = gpui::TestAppContext::build(dispatcher, None);
|
|
cx.update(|cx| {
|
|
let store = SettingsStore::test(cx);
|
|
cx.set_global(store);
|
|
editor::init(cx);
|
|
});
|
|
|
|
let corpora = [
|
|
(
|
|
"ascii",
|
|
" let chunks = snapshot.highlighted_chunks(rows.clone(), language_aware, style);",
|
|
),
|
|
(
|
|
"unicode",
|
|
"の設定を変更する — émojis 🧑\u{200d}✈\u{fe0f} und Ümläute überall, здесь тоже текст",
|
|
),
|
|
(
|
|
"sparse_invisibles",
|
|
"normal text here\u{200b}and some more text that goes on for a while without issues",
|
|
),
|
|
(
|
|
"dense_invisibles",
|
|
"a\u{200b}b\u{ad}c\u{2060}d\u{feff}e\u{200b}f\u{ad}g\u{2060}h",
|
|
),
|
|
];
|
|
|
|
let mut group = c.benchmark_group("Highlighted chunks");
|
|
for (name, line) in corpora {
|
|
let text = std::iter::repeat_n(line, LINE_COUNT)
|
|
.collect::<Vec<_>>()
|
|
.join("\n");
|
|
let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
|
|
let map = cx.new(|cx| {
|
|
DisplayMap::new(
|
|
buffer,
|
|
font("Courier"),
|
|
px(16.0),
|
|
None,
|
|
1,
|
|
1,
|
|
FoldPlaceholder::default(),
|
|
DiagnosticSeverity::Warning,
|
|
cx,
|
|
)
|
|
});
|
|
let snapshot = cx.update(|cx| map.update(cx, |map, cx| map.snapshot(cx)));
|
|
let editor_style = EditorStyle::default();
|
|
group.bench_with_input(
|
|
BenchmarkId::new("highlighted_chunks", name),
|
|
&snapshot,
|
|
|bench, snapshot| {
|
|
bench.iter(|| {
|
|
let mut total_len = 0usize;
|
|
let chunks = snapshot.highlighted_chunks(
|
|
DisplayRow(0)..DisplayRow(LINE_COUNT as u32),
|
|
language::LanguageAwareStyling {
|
|
tree_sitter: false,
|
|
diagnostics: false,
|
|
},
|
|
&editor_style,
|
|
);
|
|
for chunk in chunks {
|
|
total_len += black_box(chunk.text).len();
|
|
}
|
|
black_box(total_len);
|
|
});
|
|
},
|
|
);
|
|
}
|
|
group.finish();
|
|
}
|
|
|
|
criterion_group!(
|
|
benches,
|
|
to_tab_point_benchmark,
|
|
to_fold_point_benchmark,
|
|
create_highlight_endpoints_benchmark,
|
|
highlighted_chunks_benchmark
|
|
);
|
|
criterion_main!(benches);
|