Skip to content

Instantly share code, notes, and snippets.

@CAD97

CAD97/lib.rs Secret

Created August 11, 2022 10:02
Show Gist options
  • Save CAD97/2922d3132777310c1e22564f6c6dabdf to your computer and use it in GitHub Desktop.
Save CAD97/2922d3132777310c1e22564f6c6dabdf to your computer and use it in GitHub Desktop.
Fix rust-lang/rust#10761 (2013) with a -1/+8 patch
#![allow(unused_must_use)]
#![feature(test)]
extern crate test;
use std::fmt::{self, Write as FmtWrite};
use std::io::{self, Write as IoWrite};
use std::vec::Vec;
use test::Bencher;
struct FastWrite<W>(W);
impl<W: IoWrite> IoWrite for FastWrite<W> {
fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
self.0.write(buf)
}
fn flush(&mut self) -> Result<(), io::Error> {
self.0.flush()
}
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
self.0.write_vectored(bufs)
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.0.write_all(buf)
}
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
if let Some(s) = fmt.as_str() {
self.0.write_all(s.as_bytes())
} else {
self.0.write_fmt(fmt)
}
}
}
impl<W: FmtWrite> FmtWrite for FastWrite<W> {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.0.write_str(s)
}
fn write_char(&mut self, c: char) -> fmt::Result {
self.0.write_char(c)
}
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
if let Some(s) = args.as_str() {
self.0.write_str(s)
} else {
self.0.write_fmt(args)
}
}
}
#[bench]
fn old_vec_write_value(bh: &mut Bencher) {
bh.iter(|| {
let mut mem: Vec<u8> = Vec::new();
for _ in 0..1000 {
mem.write("abc".as_bytes());
}
});
}
#[bench]
fn new_vec_write_value(bh: &mut Bencher) {
bh.iter(|| {
let mut mem: FastWrite<Vec<u8>> = FastWrite(Vec::new());
for _ in 0..1000 {
mem.write("abc".as_bytes());
}
});
}
#[bench]
fn old_vec_write_ref(bh: &mut Bencher) {
bh.iter(|| {
let mut mem: Vec<u8> = Vec::new();
let wr = &mut mem as &mut dyn IoWrite;
for _ in 0..1000 {
wr.write("abc".as_bytes());
}
});
}
#[bench]
fn new_vec_write_ref(bh: &mut Bencher) {
bh.iter(|| {
let mut mem: FastWrite<Vec<u8>> = FastWrite(Vec::new());
let wr = &mut mem as &mut dyn IoWrite;
for _ in 0..1000 {
wr.write("abc".as_bytes());
}
});
}
#[bench]
fn old_vec_write_macro1(bh: &mut Bencher) {
bh.iter(|| {
let mut mem: Vec<u8> = Vec::new();
let wr = &mut mem as &mut dyn IoWrite;
for _ in 0..1000 {
write!(wr, "abc");
}
});
}
#[bench]
fn new_vec_write_macro1(bh: &mut Bencher) {
bh.iter(|| {
let mut mem: FastWrite<Vec<u8>> = FastWrite(Vec::new());
let wr = &mut mem as &mut dyn IoWrite;
for _ in 0..1000 {
write!(wr, "abc");
}
});
}
#[bench]
fn old_vec_write_macro2(bh: &mut Bencher) {
bh.iter(|| {
let mut mem: Vec<u8> = Vec::new();
let wr = &mut mem as &mut dyn IoWrite;
for _ in 0..1000 {
write!(wr, "{}", "abc");
}
});
}
#[bench]
fn new_vec_write_macro2(bh: &mut Bencher) {
bh.iter(|| {
let mut mem: FastWrite<Vec<u8>> = FastWrite(Vec::new());
let wr = &mut mem as &mut dyn IoWrite;
for _ in 0..1000 {
write!(wr, "{}", "abc");
}
});
}
#[bench]
fn old_vec_write_fmt(bh: &mut Bencher) {
bh.iter(|| {
let mut mem: Vec<u8> = Vec::new();
let wr = &mut mem as &mut dyn IoWrite;
for _ in 0..1000 {
wr.write_fmt(format_args!("abc"));
}
});
}
#[bench]
fn new_vec_write_fmt(bh: &mut Bencher) {
bh.iter(|| {
let mut mem: FastWrite<Vec<u8>> = FastWrite(Vec::new());
let wr = &mut mem as &mut dyn IoWrite;
for _ in 0..1000 {
wr.write_fmt(format_args!("abc"));
}
});
}
#[bench]
fn old_string_write_value(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = String::new();
for _ in 0..1000 {
mem.write_str("abc");
}
});
}
#[bench]
fn new_string_write_value(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = FastWrite(String::new());
for _ in 0..1000 {
mem.write_str("abc");
}
});
}
#[bench]
fn old_string_write_ref(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = String::new();
let wr = &mut mem as &mut dyn FmtWrite;
for _ in 0..1000 {
wr.write_str("abc");
}
});
}
#[bench]
fn new_string_write_ref(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = FastWrite(String::new());
let wr = &mut mem as &mut dyn FmtWrite;
for _ in 0..1000 {
wr.write_str("abc");
}
});
}
#[bench]
fn old_string_write_macro1(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = String::new();
let wr = &mut mem as &mut dyn FmtWrite;
for _ in 0..1000 {
write!(wr, "abc");
}
});
}
#[bench]
fn new_string_write_macro1(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = FastWrite(String::new());
let wr = &mut mem as &mut dyn FmtWrite;
for _ in 0..1000 {
write!(wr, "abc");
}
});
}
#[bench]
fn old_string_write_macro2(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = String::new();
let wr = &mut mem as &mut dyn FmtWrite;
for _ in 0..1000 {
write!(wr, "{}", "abc");
}
});
}
#[bench]
fn new_string_write_macro2(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = FastWrite(String::new());
let wr = &mut mem as &mut dyn FmtWrite;
for _ in 0..1000 {
write!(wr, "{}", "abc");
}
});
}
#[bench]
fn old_string_write_fmt(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = String::new();
let wr = &mut mem as &mut dyn FmtWrite;
for _ in 0..1000 {
wr.write_fmt(format_args!("abc"));
}
});
}
#[bench]
fn new_string_write_fmt(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = FastWrite(String::new());
let wr = &mut mem as &mut dyn FmtWrite;
for _ in 0..1000 {
wr.write_fmt(format_args!("abc"));
}
});
}
running 8 tests
test new_string_write_macro1 ... bench: 1,875 ns/iter (+/- 228)
test new_string_write_macro2 ... bench: 13,594 ns/iter (+/- 999)
test new_vec_write_macro1 ... bench: 1,637 ns/iter (+/- 175)
test new_vec_write_macro2 ... bench: 13,808 ns/iter (+/- 1,320)
test old_string_write_macro1 ... bench: 10,080 ns/iter (+/- 1,618)
test old_string_write_macro2 ... bench: 13,880 ns/iter (+/- 1,327)
test old_vec_write_macro1 ... bench: 10,037 ns/iter (+/- 779)
test old_vec_write_macro2 ... bench: 14,783 ns/iter (+/- 1,280)
--- old/src/std/io/mod.rs
+++ new/src/std/io/mod.rs
@@ -1650,8 +1650,12 @@
#[stable(feature = "rust1", since = "1.0.0")]
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> {
+ if let Some(s) = fmt.as_str() {
+ return self.write_all(s.as_bytes());
+ }
+
// Create a shim which translates a Write to a fmt::Write and saves
// off I/O errors. instead of discarding them
struct Adapter<'a, T: ?Sized + 'a> {
inner: &'a mut T,
error: Result<()>,
}
--- old/src/core/fmt/mod.rs
+++ new/src/core/fmt/mod.rs
@@ -186,4 +186,8 @@
#[stable(feature = "rust1", since = "1.0.0")]
fn write_fmt(mut self: &mut Self, args: Arguments<'_>) -> Result {
+ if let Some(s) = args.as_str() {
+ self.write_str(s)
+ } else {
- write(&mut self, args)
+ write(&mut self, args)
+ }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment