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 assets::Assets.load_test_fonts(cx);
126 theme::init(theme::LoadThemes::JustBase, cx);
127 // release_channel::init(SemanticVersion::default(), cx);
128 client::init_settings(cx);
129 language::init(cx);
130 workspace::init_settings(cx);
131 Project::init_settings(cx);
132 editor::init(cx);
133 });
134
135 let mut criterion: criterion::Criterion<_> =
136 (criterion::Criterion::default()).configure_from_args();
137
138 // setup app context
139 let mut group = criterion.benchmark_group("Time to render");
140 group.bench_with_input(
141 BenchmarkId::new("editor_render", "TestAppContext"),
142 &cx,
143 editor_render,
144 );
145
146 group.finish();
147
148 let text = String::from_iter(["char"; 1000]);
149 let mut group = criterion.benchmark_group("Build buffer with one long line");
150 group.bench_with_input(
151 BenchmarkId::new("editor_with_one_long_line", "(String, TestAppContext )"),
152 &(text, cx.clone()),
153 open_editor_with_one_long_line,
154 );
155
156 group.finish();
157
158 let mut group = criterion.benchmark_group("multi cursor edits");
159 group.bench_with_input(
160 BenchmarkId::new("editor_input_with_1000_cursors", "TestAppContext"),
161 &cx,
162 editor_input_with_1000_cursors,
163 );
164 group.finish();
165}
166
167fn main() {
168 benches();
169 criterion::Criterion::default()
170 .configure_from_args()
171 .final_summary();
172}