diff --git a/bench/Cargo.toml b/bench/Cargo.toml index 4b095f6..113ff28 100644 --- a/bench/Cargo.toml +++ b/bench/Cargo.toml @@ -23,3 +23,7 @@ harness = false [[bench]] name = "search" harness = false + +[[bench]] +name = "cursor" +harness = false diff --git a/bench/benches/cursor.rs b/bench/benches/cursor.rs new file mode 100644 index 0000000..631f5f9 --- /dev/null +++ b/bench/benches/cursor.rs @@ -0,0 +1,102 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use tui_textarea::{CursorMove, TextArea}; +use tui_textarea_bench::{dummy_terminal, TerminalExt, LOREM}; + +#[derive(Clone, Copy)] +enum Restore { + TopLeft, + BottomLeft, + BottomRight, + None, +} + +impl Restore { + fn cursor_move(self) -> Option { + match self { + Self::TopLeft => Some(CursorMove::Jump(0, 0)), + Self::BottomLeft => Some(CursorMove::Jump(u16::MAX, 0)), + Self::BottomRight => Some(CursorMove::Jump(u16::MAX, u16::MAX)), + Self::None => None, + } + } +} + +fn run(moves: &[CursorMove], restore: Restore, repeat: usize) -> (usize, usize) { + let mut lines = Vec::with_capacity(LOREM.len() * 2 + 1); + lines.extend(LOREM.iter().map(|s| s.to_string())); + lines.push("".to_string()); + lines.extend(LOREM.iter().map(|s| s.to_string())); + + let mut textarea = TextArea::new(lines); + let mut term = dummy_terminal(); + + let mut prev = textarea.cursor(); + for _ in 0..repeat { + for m in moves { + textarea.move_cursor(*m); + term.draw_textarea(&textarea); + } + if let Some(m) = restore.cursor_move() { + if textarea.cursor() == prev { + textarea.move_cursor(m); + prev = textarea.cursor(); + } + } + } + + textarea.cursor() +} + +fn move_char(c: &mut Criterion) { + c.bench_function("cursor::char::forward", |b| { + b.iter(|| black_box(run(&[CursorMove::Forward], Restore::TopLeft, 1000))) + }); + c.bench_function("cursor::char::back", |b| { + b.iter(|| black_box(run(&[CursorMove::Back], Restore::BottomRight, 1000))) + }); + c.bench_function("cursor::char::down", |b| { + b.iter(|| black_box(run(&[CursorMove::Down], Restore::TopLeft, 1000))) + }); + c.bench_function("cursor::char::up", |b| { + b.iter(|| black_box(run(&[CursorMove::Up], Restore::BottomLeft, 1000))) + }); +} +fn move_word(c: &mut Criterion) { + c.bench_function("cursor::word::forward", |b| { + b.iter(|| black_box(run(&[CursorMove::WordForward], Restore::TopLeft, 1000))) + }); + c.bench_function("cursor::word::back", |b| { + b.iter(|| black_box(run(&[CursorMove::WordBack], Restore::BottomRight, 1000))) + }); +} +fn move_paragraph(c: &mut Criterion) { + c.bench_function("cursor::paragraph::down", |b| { + b.iter(|| black_box(run(&[CursorMove::ParagraphForward], Restore::TopLeft, 1000))) + }); + c.bench_function("cursor::paragraph::up", |b| { + b.iter(|| black_box(run(&[CursorMove::ParagraphBack], Restore::BottomLeft, 1000))) + }); +} +fn move_edge(c: &mut Criterion) { + c.bench_function("cursor::edge::head_end", |b| { + b.iter(|| { + black_box(run( + &[CursorMove::End, CursorMove::Head], + Restore::None, + 500, + )) + }) + }); + c.bench_function("cursor::edge::top_bottom", |b| { + b.iter(|| { + black_box(run( + &[CursorMove::Bottom, CursorMove::Top], + Restore::None, + 500, + )) + }) + }); +} + +criterion_group!(cursor, move_char, move_word, move_paragraph, move_edge); +criterion_main!(cursor); diff --git a/bench/src/lib.rs b/bench/src/lib.rs index dba3a67..aadd5b8 100644 --- a/bench/src/lib.rs +++ b/bench/src/lib.rs @@ -31,8 +31,8 @@ pub struct DummyBackend { impl Default for DummyBackend { fn default() -> Self { Self { - width: 80, - height: 24, + width: 40, + height: 12, cursor: (0, 0), } }