Skip to content

Commit 555db2d

Browse files
authored
Rollup merge of #82248 - nhwn:optimize-counting-digits, r=varkor
Optimize counting digits in line numbers during error reporting Replaces `.to_string().len()` with simple loop and integer division, which avoids an unnecessary allocation. Although I couldn't figure out how to directly profile `rustc`'s error reporting, I ran a microbenchmark on my machine (2.9 GHz Dual-Core Intel Core i5) on the two strategies for `0..100_000`, and the results seem promising: ``` test to_string_len ... bench: 12,124,792 ns/iter (+/- 700,652) test while_loop ... bench: 30,333 ns/iter (+/- 562) ``` The x86_64 disassembly reduces integer division to a multiplication + shift, so I don't think there's any problems with using integer division. For more (micro)optimization, it would be nice if we could avoid the initial check to see if the line number is nonzero, but I don't think `self.get_max_line_num(span, children)` _guarantees_ a nonzero line number.
2 parents 5ca94cd + 8a5c568 commit 555db2d

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

compiler/rustc_errors/src/emitter.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -1713,7 +1713,18 @@ impl EmitterWriter {
17131713
let max_line_num_len = if self.ui_testing {
17141714
ANONYMIZED_LINE_NUM.len()
17151715
} else {
1716-
self.get_max_line_num(span, children).to_string().len()
1716+
// Instead of using .to_string().len(), we iteratively count the
1717+
// number of digits to avoid allocation. This strategy has sizable
1718+
// performance gains over the old string strategy.
1719+
let mut n = self.get_max_line_num(span, children);
1720+
let mut num_digits = 0;
1721+
loop {
1722+
num_digits += 1;
1723+
n /= 10;
1724+
if n == 0 {
1725+
break num_digits;
1726+
}
1727+
}
17171728
};
17181729

17191730
match self.emit_message_default(span, message, code, level, max_line_num_len, false) {

0 commit comments

Comments
 (0)