editor_render.rs

  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}