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