Rollup merge of #57537 - sinkuu:fmt_perf, r=alexcrichton

Small perf improvement for fmt

Added benchmark is based on #10761
This commit is contained in:
Mazdak Farrokhzad 2019-01-22 12:20:23 +01:00 committed by GitHub
commit e437861d27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 130 additions and 5 deletions

110
src/libcore/benches/fmt.rs Normal file
View File

@ -0,0 +1,110 @@
use std::io::{self, Write as IoWrite};
use std::fmt::{self, Write as FmtWrite};
use test::Bencher;
#[bench]
fn write_vec_value(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = Vec::new();
for _ in 0..1000 {
mem.write_all("abc".as_bytes()).unwrap();
}
});
}
#[bench]
fn write_vec_ref(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = Vec::new();
let wr = &mut mem as &mut dyn io::Write;
for _ in 0..1000 {
wr.write_all("abc".as_bytes()).unwrap();
}
});
}
#[bench]
fn write_vec_macro1(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = Vec::new();
let wr = &mut mem as &mut dyn io::Write;
for _ in 0..1000 {
write!(wr, "abc").unwrap();
}
});
}
#[bench]
fn write_vec_macro2(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = Vec::new();
let wr = &mut mem as &mut dyn io::Write;
for _ in 0..1000 {
write!(wr, "{}", "abc").unwrap();
}
});
}
#[bench]
fn write_vec_macro_debug(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = Vec::new();
let wr = &mut mem as &mut dyn io::Write;
for _ in 0..1000 {
write!(wr, "{:?}", "").unwrap();
}
});
}
#[bench]
fn write_str_value(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = String::new();
for _ in 0..1000 {
mem.write_str("abc").unwrap();
}
});
}
#[bench]
fn write_str_ref(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = String::new();
let wr = &mut mem as &mut dyn fmt::Write;
for _ in 0..1000 {
wr.write_str("abc").unwrap();
}
});
}
#[bench]
fn write_str_macro1(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = String::new();
for _ in 0..1000 {
write!(mem, "abc").unwrap();
}
});
}
#[bench]
fn write_str_macro2(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = String::new();
let wr = &mut mem as &mut dyn fmt::Write;
for _ in 0..1000 {
write!(wr, "{}", "abc").unwrap();
}
});
}
#[bench]
fn write_str_macro_debug(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = String::new();
let wr = &mut mem as &mut dyn fmt::Write;
for _ in 0..1000 {
write!(wr, "{:?}", "").unwrap();
}
});
}

View File

@ -11,3 +11,4 @@ mod iter;
mod num; mod num;
mod ops; mod ops;
mod slice; mod slice;
mod fmt;

View File

@ -1006,28 +1006,30 @@ pub fn write(output: &mut dyn Write, args: Arguments) -> Result {
curarg: args.args.iter(), curarg: args.args.iter(),
}; };
let mut pieces = args.pieces.iter(); let mut idx = 0;
match args.fmt { match args.fmt {
None => { None => {
// We can use default formatting parameters for all arguments. // We can use default formatting parameters for all arguments.
for (arg, piece) in args.args.iter().zip(pieces.by_ref()) { for (arg, piece) in args.args.iter().zip(args.pieces.iter()) {
formatter.buf.write_str(*piece)?; formatter.buf.write_str(*piece)?;
(arg.formatter)(arg.value, &mut formatter)?; (arg.formatter)(arg.value, &mut formatter)?;
idx += 1;
} }
} }
Some(fmt) => { Some(fmt) => {
// Every spec has a corresponding argument that is preceded by // Every spec has a corresponding argument that is preceded by
// a string piece. // a string piece.
for (arg, piece) in fmt.iter().zip(pieces.by_ref()) { for (arg, piece) in fmt.iter().zip(args.pieces.iter()) {
formatter.buf.write_str(*piece)?; formatter.buf.write_str(*piece)?;
formatter.run(arg)?; formatter.run(arg)?;
idx += 1;
} }
} }
} }
// There can be only one trailing string piece left. // There can be only one trailing string piece left.
if let Some(piece) = pieces.next() { if let Some(piece) = args.pieces.get(idx) {
formatter.buf.write_str(*piece)?; formatter.buf.write_str(*piece)?;
} }

View File

@ -72,6 +72,15 @@ pub enum Position<'a> {
ArgumentNamed(&'a str), ArgumentNamed(&'a str),
} }
impl Position<'_> {
pub fn index(&self) -> Option<usize> {
match self {
ArgumentIs(i) | ArgumentImplicitlyIs(i) => Some(*i),
_ => None,
}
}
}
/// Enum of alignments which are supported. /// Enum of alignments which are supported.
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
pub enum Alignment { pub enum Alignment {

View File

@ -493,7 +493,10 @@ impl<'a, 'b> Context<'a, 'b> {
let fill = arg.format.fill.unwrap_or(' '); let fill = arg.format.fill.unwrap_or(' ');
if *arg != simple_arg || fill != ' ' { let pos_simple =
arg.position.index() == simple_arg.position.index();
if !pos_simple || arg.format != simple_arg.format || fill != ' ' {
self.all_pieces_simple = false; self.all_pieces_simple = false;
} }