diff options
| author | Mark Rousskov <mark.simulacrum@gmail.com> | 2021-05-16 21:31:18 -0400 |
|---|---|---|
| committer | Mark Rousskov <mark.simulacrum@gmail.com> | 2021-05-17 09:29:02 -0400 |
| commit | 80ac15f667c32b1e441cffaa3237cae2990cc152 (patch) | |
| tree | a86a48b4fa77c0b767b6a70073532b0e9366367a | |
| parent | 2a245f40a19c9a60b3be33c959eb5cfb0ad163c6 (diff) | |
| download | rust-80ac15f667c32b1e441cffaa3237cae2990cc152.tar.gz rust-80ac15f667c32b1e441cffaa3237cae2990cc152.zip | |
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.
| -rw-r--r-- | library/alloc/src/string.rs | 5 | ||||
| -rw-r--r-- | library/core/src/fmt/mod.rs | 32 |
2 files changed, 26 insertions, 11 deletions
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index e6252452470..ec09595e357 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2323,9 +2323,10 @@ impl<T: fmt::Display + ?Sized> ToString for T { // to try to remove it. #[inline] default fn to_string(&self) -> String { - use fmt::Write; let mut buf = String::new(); - buf.write_fmt(format_args!("{}", self)) + let mut formatter = core::fmt::Formatter::new(&mut buf); + // Bypass format_args!() to avoid write_str with zero-length strs + fmt::Display::fmt(self, &mut formatter) .expect("a Display implementation returned an error unexpectedly"); buf } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 87042d95fbe..5cb3c9062fe 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -221,6 +221,28 @@ pub struct Formatter<'a> { buf: &'a mut (dyn Write + 'a), } +impl<'a> Formatter<'a> { + /// Creates a new formatter with default settings. + /// + /// This can be used as a micro-optimization in cases where a full `Arguments` + /// structure (as created by `format_args!`) is not necessary; `Arguments` + /// is a little more expensive to use in simple formatting scenarios. + /// + /// Currently not intended for use outside of the standard library. + #[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")] + #[doc(hidden)] + pub fn new(buf: &'a mut (dyn Write + 'a)) -> Formatter<'a> { + Formatter { + flags: 0, + fill: ' ', + align: rt::v1::Alignment::Unknown, + width: None, + precision: None, + buf, + } + } +} + // NB. Argument is essentially an optimized partially applied formatting function, // equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`. @@ -1075,15 +1097,7 @@ pub trait UpperExp { /// [`write!`]: crate::write! #[stable(feature = "rust1", since = "1.0.0")] pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { - let mut formatter = Formatter { - flags: 0, - width: None, - precision: None, - buf: output, - align: rt::v1::Alignment::Unknown, - fill: ' ', - }; - + let mut formatter = Formatter::new(output); let mut idx = 0; match args.fmt { |
