1use criterion::{Bencher, BenchmarkId};
2use editor::{
3 Editor, EditorMode, MultiBuffer,
4 actions::{DeleteToPreviousWordStart, SelectAll, SplitSelectionIntoLines},
5};
6use gpui::{AppContext, Focusable as _, TestAppContext, TestDispatcher};
7use rand::{Rng as _, SeedableRng as _, rngs::StdRng};
8use settings::SettingsStore;
9use ui::IntoElement;
10use util::RandomCharIter;
11
12fn editor_input_with_1000_cursors(bencher: &mut Bencher<'_>, cx: &TestAppContext) {
13 let mut cx = cx.clone();
14 let text = String::from_iter(["line:\n"; 1000]);
15 let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
16
17 let cx = cx.add_empty_window();
18 let editor = cx.update(|window, cx| {
19 let editor = cx.new(|cx| {
20 let mut editor = Editor::new(EditorMode::full(), buffer, None, window, cx);
21 editor.set_style(editor::EditorStyle::default(), window, cx);
22 editor.select_all(&SelectAll, window, cx);
23 editor.split_selection_into_lines(
24 &SplitSelectionIntoLines {
25 keep_selections: true,
26 },
27 window,
28 cx,
29 );
30 editor
31 });
32 window.focus(&editor.focus_handle(cx));
33 editor
34 });
35
36 bencher.iter(|| {
37 cx.update(|window, cx| {
38 editor.update(cx, |editor, cx| {
39 editor.handle_input("hello world", window, cx);
40 editor.delete_to_previous_word_start(
41 &DeleteToPreviousWordStart {
42 ignore_newlines: false,
43 ignore_brackets: false,
44 },
45 window,
46 cx,
47 );
48 editor.delete_to_previous_word_start(
49 &DeleteToPreviousWordStart {
50 ignore_newlines: false,
51 ignore_brackets: false,
52 },
53 window,
54 cx,
55 );
56 });
57 })
58 });
59}
60
61fn open_editor_with_one_long_line(bencher: &mut Bencher<'_>, args: &(String, TestAppContext)) {
62 let (text, cx) = args;
63 let mut cx = cx.clone();
64
65 bencher.iter(|| {
66 let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
67
68 let cx = cx.add_empty_window();
69 let _ = cx.update(|window, cx| {
70 let editor = cx.new(|cx| {
71 let mut editor = Editor::new(EditorMode::full(), buffer, None, window, cx);
72 editor.set_style(editor::EditorStyle::default(), window, cx);
73 editor
74 });
75 window.focus(&editor.focus_handle(cx));
76 editor
77 });
78 });
79}
80
81fn editor_render(bencher: &mut Bencher<'_>, cx: &TestAppContext) {
82 let mut cx = cx.clone();
83 let buffer = cx.update(|cx| {
84 let mut rng = StdRng::seed_from_u64(1);
85 let text_len = rng.random_range(10000..90000);
86 if rng.random() {
87 let text = RandomCharIter::new(&mut rng)
88 .take(text_len)
89 .collect::<String>();
90 MultiBuffer::build_simple(&text, cx)
91 } else {
92 MultiBuffer::build_random(&mut rng, cx)
93 }
94 });
95
96 let cx = cx.add_empty_window();
97 let editor = cx.update(|window, cx| {
98 let editor = cx.new(|cx| {
99 let mut editor = Editor::new(EditorMode::full(), buffer, None, window, cx);
100 editor.set_style(editor::EditorStyle::default(), window, cx);
101 editor
102 });
103 window.focus(&editor.focus_handle(cx));
104 editor
105 });
106
107 bencher.iter(|| {
108 cx.update(|window, cx| {
109 // editor.update(cx, |editor, cx| editor.move_down(&MoveDown, window, cx));
110 let mut view = editor.clone().into_any_element();
111 let _ = view.request_layout(window, cx);
112 let _ = view.prepaint(window, cx);
113 view.paint(window, cx);
114 });
115 })
116}
117
118pub fn benches() {
119 let dispatcher = TestDispatcher::new(StdRng::seed_from_u64(1));
120 let cx = gpui::TestAppContext::build(dispatcher, None);
121 cx.update(|cx| {
122 let store = SettingsStore::test(cx);
123 cx.set_global(store);
124 assets::Assets.load_test_fonts(cx);
125 theme::init(theme::LoadThemes::JustBase, cx);
126 // release_channel::init(SemanticVersion::default(), cx);
127 editor::init(cx);
128 });
129
130 let mut criterion: criterion::Criterion<_> =
131 (criterion::Criterion::default()).configure_from_args();
132
133 // setup app context
134 let mut group = criterion.benchmark_group("Time to render");
135 group.bench_with_input(
136 BenchmarkId::new("editor_render", "TestAppContext"),
137 &cx,
138 editor_render,
139 );
140
141 group.finish();
142
143 let text = String::from_iter(["char"; 1000]);
144 let mut group = criterion.benchmark_group("Build buffer with one long line");
145 group.bench_with_input(
146 BenchmarkId::new("editor_with_one_long_line", "(String, TestAppContext )"),
147 &(text, cx.clone()),
148 open_editor_with_one_long_line,
149 );
150
151 group.finish();
152
153 let mut group = criterion.benchmark_group("multi cursor edits");
154 group.bench_with_input(
155 BenchmarkId::new("editor_input_with_1000_cursors", "TestAppContext"),
156 &cx,
157 editor_input_with_1000_cursors,
158 );
159 group.finish();
160}
161
162fn main() {
163 benches();
164 criterion::Criterion::default()
165 .configure_from_args()
166 .final_summary();
167}