Optimize indentation in the pretty printer.

Currently the pretty-printer calls `write!` for every space of
indentation. On some workloads the indentation level can exceed 100, and
a faster implementation reduces instruction counts by up to 7% on a few
workloads.
This commit is contained in:
Nicholas Nethercote 2019-03-29 08:32:13 +11:00
parent 4c27fb19ba
commit 606f3158bf

View file

@ -300,6 +300,8 @@ impl Default for BufEntry {
}
}
const SPACES: [u8; 128] = [b' '; 128];
impl<'a> Printer<'a> {
pub fn last_token(&mut self) -> Token {
self.buf[self.right].token.clone()
@ -580,10 +582,24 @@ impl<'a> Printer<'a> {
debug!("print String({})", s);
// assert!(len <= space);
self.space -= len;
while self.pending_indentation > 0 {
write!(self.out, " ")?;
self.pending_indentation -= 1;
// Write the pending indent. A more concise way of doing this would be:
//
// write!(self.out, "{: >n$}", "", n = self.pending_indentation as usize)?;
//
// But that is significantly slower than using `SPACES`. This code is
// sufficiently hot, and indents can get sufficiently large, that the
// difference is significant on some workloads.
let spaces_len = SPACES.len() as isize;
while self.pending_indentation >= spaces_len {
self.out.write_all(&SPACES)?;
self.pending_indentation -= spaces_len;
}
if self.pending_indentation > 0 {
self.out.write_all(&SPACES[0..self.pending_indentation as usize])?;
self.pending_indentation = 0;
}
write!(self.out, "{}", s)
}