Skip to content

Commit 80ac15f

Browse files
Optimize default ToString impl
This avoids a zero-length write_str call, which boils down to a zero-length memmove and ultimately costs quite a few instructions on some workloads. This is approximately a 0.33% instruction count win on diesel-check.
1 parent 2a245f4 commit 80ac15f

File tree

2 files changed

+26
-11
lines changed

2 files changed

+26
-11
lines changed

library/alloc/src/string.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2323,9 +2323,10 @@ impl<T: fmt::Display + ?Sized> ToString for T {
23232323
// to try to remove it.
23242324
#[inline]
23252325
default fn to_string(&self) -> String {
2326-
use fmt::Write;
23272326
let mut buf = String::new();
2328-
buf.write_fmt(format_args!("{}", self))
2327+
let mut formatter = core::fmt::Formatter::new(&mut buf);
2328+
// Bypass format_args!() to avoid write_str with zero-length strs
2329+
fmt::Display::fmt(self, &mut formatter)
23292330
.expect("a Display implementation returned an error unexpectedly");
23302331
buf
23312332
}

library/core/src/fmt/mod.rs

+23-9
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,28 @@ pub struct Formatter<'a> {
221221
buf: &'a mut (dyn Write + 'a),
222222
}
223223

224+
impl<'a> Formatter<'a> {
225+
/// Creates a new formatter with default settings.
226+
///
227+
/// This can be used as a micro-optimization in cases where a full `Arguments`
228+
/// structure (as created by `format_args!`) is not necessary; `Arguments`
229+
/// is a little more expensive to use in simple formatting scenarios.
230+
///
231+
/// Currently not intended for use outside of the standard library.
232+
#[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")]
233+
#[doc(hidden)]
234+
pub fn new(buf: &'a mut (dyn Write + 'a)) -> Formatter<'a> {
235+
Formatter {
236+
flags: 0,
237+
fill: ' ',
238+
align: rt::v1::Alignment::Unknown,
239+
width: None,
240+
precision: None,
241+
buf,
242+
}
243+
}
244+
}
245+
224246
// NB. Argument is essentially an optimized partially applied formatting function,
225247
// equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`.
226248

@@ -1075,15 +1097,7 @@ pub trait UpperExp {
10751097
/// [`write!`]: crate::write!
10761098
#[stable(feature = "rust1", since = "1.0.0")]
10771099
pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
1078-
let mut formatter = Formatter {
1079-
flags: 0,
1080-
width: None,
1081-
precision: None,
1082-
buf: output,
1083-
align: rt::v1::Alignment::Unknown,
1084-
fill: ' ',
1085-
};
1086-
1100+
let mut formatter = Formatter::new(output);
10871101
let mut idx = 0;
10881102

10891103
match args.fmt {

0 commit comments

Comments
 (0)