Skip to content

Commit d687e70

Browse files
authored
Unrolled build for rust-lang#124551
Rollup merge of rust-lang#124551 - Swatinem:debug-str-bench, r=cuviper Add benchmarks for `impl Debug for str` In order to inform future perf improvements and prevent regressions, lets add some benchmarks that stress `impl Debug for str`. --- As I am currently working on improving the perf in rust-lang#121150, its nice to have these benchmarks. Writing them, I also saw that escapes are written out one char at a time, even though other parts of the code are already optimizing that via `as_str`, which I intend to do as well as a followup improvement. r? ``@cuviper`` ☝🏻 as you were also assigned to rust-lang#121150, CC ``@the8472`` if you want to steal the review :-)
2 parents 98dabb6 + 5fe296c commit d687e70

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

library/core/benches/str.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use test::{black_box, Bencher};
33

44
mod char_count;
55
mod corpora;
6+
mod debug;
67
mod iter;
78

89
#[bench]

library/core/benches/str/debug.rs

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//! This primarily benchmarks `impl Debug for str`,
2+
//! and it also explicitly tests that we minimizes calls to the underlying `Write`r.
3+
//! While that is an implementation detail and there are no guarantees about it,
4+
//! we should still try to minimize those calls over time rather than regress them.
5+
6+
use std::fmt::{self, Write};
7+
use test::{black_box, Bencher};
8+
9+
#[derive(Default)]
10+
struct CountingWriter {
11+
buf: String,
12+
write_calls: usize,
13+
}
14+
15+
impl Write for CountingWriter {
16+
fn write_str(&mut self, s: &str) -> fmt::Result {
17+
self.buf.push_str(s);
18+
self.write_calls += 1;
19+
Ok(())
20+
}
21+
}
22+
23+
fn assert_fmt(s: &str, expected: &str, expected_write_calls: usize) {
24+
let mut w = CountingWriter::default();
25+
26+
write!(&mut w, "{s:?}").unwrap();
27+
assert_eq!(s.len(), 64);
28+
assert_eq!(w.buf, expected);
29+
assert_eq!(w.write_calls, expected_write_calls);
30+
}
31+
32+
#[bench]
33+
fn ascii_only(b: &mut Bencher) {
34+
let s = "just a bit of ascii text that has no escapes. 64 bytes exactly!!";
35+
assert_fmt(s, r#""just a bit of ascii text that has no escapes. 64 bytes exactly!!""#, 3);
36+
b.iter(|| {
37+
black_box(format!("{:?}", black_box(s)));
38+
});
39+
}
40+
41+
#[bench]
42+
fn ascii_escapes(b: &mut Bencher) {
43+
let s = "some\tmore\tascii\ttext\nthis time with some \"escapes\", also 64 byte";
44+
assert_fmt(
45+
s,
46+
r#""some\tmore\tascii\ttext\nthis time with some \"escapes\", also 64 byte""#,
47+
21,
48+
);
49+
b.iter(|| {
50+
black_box(format!("{:?}", black_box(s)));
51+
});
52+
}
53+
54+
#[bench]
55+
fn some_unicode(b: &mut Bencher) {
56+
let s = "egy kis szöveg néhány unicode betűvel. legyen ez is 64 byte.";
57+
assert_fmt(s, r#""egy kis szöveg néhány unicode betűvel. legyen ez is 64 byte.""#, 3);
58+
b.iter(|| {
59+
black_box(format!("{:?}", black_box(s)));
60+
});
61+
}
62+
63+
#[bench]
64+
fn mostly_unicode(b: &mut Bencher) {
65+
let s = "предложение из кириллических букв.";
66+
assert_fmt(s, r#""предложение из кириллических букв.""#, 3);
67+
b.iter(|| {
68+
black_box(format!("{:?}", black_box(s)));
69+
});
70+
}
71+
72+
#[bench]
73+
fn mixed(b: &mut Bencher) {
74+
let s = "\"❤️\"\n\"hűha ez betű\"\n\"кириллических букв\".";
75+
assert_fmt(s, r#""\"❤\u{fe0f}\"\n\"hűha ez betű\"\n\"кириллических букв\".""#, 36);
76+
b.iter(|| {
77+
black_box(format!("{:?}", black_box(s)));
78+
});
79+
}

0 commit comments

Comments
 (0)