Skip to content

Commit

Permalink
Merge pull request #354 from mgeisler/indent-benchmark
Browse files Browse the repository at this point in the history
Make `indent` faster by preallocating the output string
  • Loading branch information
mgeisler committed May 13, 2021
2 parents 7a9a65c + 19bb2ef commit e505b89
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 1 deletion.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ name = "linear"
harness = false
path = "benches/linear.rs"

[[bench]]
name = "indent"
harness = false
path = "benches/indent.rs"

[features]
default = ["unicode-linebreak", "unicode-width", "smawk"]

Expand Down
24 changes: 24 additions & 0 deletions benches/indent.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use criterion::Criterion;
use criterion::{criterion_group, criterion_main};

pub fn benchmark(c: &mut Criterion) {
// Generate a piece of text with some empty lines.
let words_per_line = [
5, 10, 15, 5, 0, 10, 5, 0, 5, 10, // 10 lines
10, 10, 5, 5, 5, 5, 15, 10, 5, 0, // 20 lines
10, 5, 0, 0, 15, 10, 10, 5, 5, 5, // 30 lines
15, 5, 0, 10, 5, 0, 0, 15, 5, 10, // 40 lines
5, 15, 0, 5, 15, 0, 10, 10, 5, 5, // 50 lines
];
let mut text = String::new();
for (line_no, word_count) in words_per_line.iter().enumerate() {
text.push_str(&lipsum::lipsum_words_from_seed(*word_count, line_no as u64));
text.push('\n');
}
assert_eq!(text.len(), 2304); // The size for reference.

c.bench_function("indent", |b| b.iter(|| textwrap::indent(&text, " ")));
}

criterion_group!(benches, benchmark);
criterion_main!(benches);
6 changes: 5 additions & 1 deletion src/indentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@
/// assert_eq!(indent(" \t Foo ", "->"), "-> \t Foo ");
/// ```
pub fn indent(s: &str, prefix: &str) -> String {
let mut result = String::new();
// We know we'll need more than s.len() bytes for the output, but
// without counting '\n' characters (which is somewhat slow), we
// don't know exactly how much. However, we can preemptively do
// the first doubling of the output size.
let mut result = String::with_capacity(2 * s.len());
let trimmed_prefix = prefix.trim_end();
for (idx, line) in s.split_terminator('\n').enumerate() {
if idx > 0 {
Expand Down

0 comments on commit e505b89

Please sign in to comment.