Auto merge of #121001 - nyurik:optimize-core-fmt, r=cuviper

perf: improve write_fmt to handle simple strings

In case format string has no arguments, simplify its implementation with a direct call to `output.write_str(value)`. This builds on `@dtolnay` original [suggestion](https://github.com/serde-rs/serde/pull/2697#issuecomment-1940376414). This does not change any expectations because the original `fn write()` implementation calls `write_str` for parts of the format string.

```rust
write!(f, "text")  ->  f.write_str("text")
```

```diff
 /// [`write!`]: crate::write!
+#[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
+    if let Some(s) = args.as_str() { output.write_str(s) } else { write_internal(output, args) }
+}
+
+/// Actual implementation of the [`write`], but without the simple string optimization.
+fn write_internal(output: &mut dyn Write, args: Arguments<'_>) -> Result {
     let mut formatter = Formatter::new(output);
     let mut idx = 0;
```

* Hopefully it will improve the simple case for the https://github.com/rust-lang/rust/issues/99012
* Another related (original?) issues #10761
* Previous similar attempt to fix it by by `@Kobzol` #100700

CC: `@m-ou-se` as probably the biggest expert in everything `format!`
This commit is contained in:
bors 2024-03-05 05:33:17 +00:00
commit 5a1e5449c8

View File

@ -1102,8 +1102,14 @@ pub trait UpperExp {
/// ``` /// ```
/// ///
/// [`write!`]: crate::write! /// [`write!`]: crate::write!
#[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
if let Some(s) = args.as_str() { output.write_str(s) } else { write_internal(output, args) }
}
/// Actual implementation of the [`write()`], but without the simple string optimization.
fn write_internal(output: &mut dyn Write, args: Arguments<'_>) -> Result {
let mut formatter = Formatter::new(output); let mut formatter = Formatter::new(output);
let mut idx = 0; let mut idx = 0;