rope_benchmark.rs

  1use std::ops::Range;
  2
  3use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion, Throughput};
  4use rand::prelude::*;
  5use rand::rngs::StdRng;
  6use rope::Rope;
  7use util::RandomCharIter;
  8
  9fn generate_random_text(mut rng: StdRng, text_len: usize) -> String {
 10    RandomCharIter::new(&mut rng).take(text_len).collect()
 11}
 12
 13fn generate_random_rope(rng: StdRng, text_len: usize) -> Rope {
 14    let text = generate_random_text(rng, text_len);
 15    let mut rope = Rope::new();
 16    rope.push(&text);
 17    rope
 18}
 19
 20fn generate_random_rope_ranges(mut rng: StdRng, rope: &Rope) -> Vec<Range<usize>> {
 21    let range_max_len = 50;
 22    let num_ranges = rope.len() / range_max_len;
 23
 24    let mut ranges = Vec::new();
 25    let mut start = 0;
 26    for _ in 0..num_ranges {
 27        let range_start = rope.clip_offset(
 28            rng.gen_range(start..=(start + range_max_len)),
 29            sum_tree::Bias::Left,
 30        );
 31        let range_end = rope.clip_offset(
 32            rng.gen_range(range_start..(range_start + range_max_len)),
 33            sum_tree::Bias::Right,
 34        );
 35
 36        let range = range_start..range_end;
 37        if !range.is_empty() {
 38            ranges.push(range);
 39        }
 40
 41        start = range_end + 1;
 42    }
 43
 44    ranges
 45}
 46
 47fn rope_benchmarks(c: &mut Criterion) {
 48    static SEED: u64 = 9999;
 49    static KB: usize = 1024;
 50
 51    let rng = StdRng::seed_from_u64(SEED);
 52    let sizes = [4 * KB, 64 * KB];
 53
 54    let mut group = c.benchmark_group("push");
 55    for size in sizes.iter() {
 56        group.throughput(Throughput::Bytes(*size as u64));
 57        group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &size| {
 58            let text = generate_random_text(rng.clone(), *size);
 59
 60            b.iter(|| {
 61                let mut rope = Rope::new();
 62                for _ in 0..10 {
 63                    rope.push(&text);
 64                }
 65            });
 66        });
 67    }
 68    group.finish();
 69
 70    let mut group = c.benchmark_group("append");
 71    for size in sizes.iter() {
 72        group.throughput(Throughput::Bytes(*size as u64));
 73        group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &size| {
 74            let mut random_ropes = Vec::new();
 75            for _ in 0..5 {
 76                random_ropes.push(generate_random_rope(rng.clone(), *size));
 77            }
 78
 79            b.iter(|| {
 80                let mut rope_b = Rope::new();
 81                for rope in &random_ropes {
 82                    rope_b.append(rope.clone())
 83                }
 84            });
 85        });
 86    }
 87    group.finish();
 88
 89    let mut group = c.benchmark_group("slice");
 90    for size in sizes.iter() {
 91        group.throughput(Throughput::Bytes(*size as u64));
 92        group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &size| {
 93            let rope = generate_random_rope(rng.clone(), *size);
 94
 95            b.iter_batched(
 96                || generate_random_rope_ranges(rng.clone(), &rope),
 97                |ranges| {
 98                    for range in ranges.iter() {
 99                        rope.slice(range.clone());
100                    }
101                },
102                BatchSize::SmallInput,
103            );
104        });
105    }
106    group.finish();
107
108    let mut group = c.benchmark_group("bytes_in_range");
109    for size in sizes.iter() {
110        group.throughput(Throughput::Bytes(*size as u64));
111        group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &size| {
112            let rope = generate_random_rope(rng.clone(), *size);
113
114            b.iter_batched(
115                || generate_random_rope_ranges(rng.clone(), &rope),
116                |ranges| {
117                    for range in ranges.iter() {
118                        let bytes = rope.bytes_in_range(range.clone());
119                        assert!(bytes.into_iter().count() > 0);
120                    }
121                },
122                BatchSize::SmallInput,
123            );
124        });
125    }
126    group.finish();
127
128    let mut group = c.benchmark_group("chars");
129    for size in sizes.iter() {
130        group.throughput(Throughput::Bytes(*size as u64));
131        group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &size| {
132            let rope = generate_random_rope(rng.clone(), *size);
133
134            b.iter_with_large_drop(|| {
135                let chars = rope.chars().count();
136                assert!(chars > 0);
137            });
138        });
139    }
140    group.finish();
141}
142
143criterion_group!(benches, rope_benchmarks);
144criterion_main!(benches);