From 426f8cba64e34bffc303bc53c995cb2ff30772c0 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Wed, 9 Apr 2025 18:54:04 +0000 Subject: [PATCH] perf(codegen): reduce checks printing strings (#10341) Speed up printing strings. I had wrongly assumed that `bytes.next().unwrap_unchecked()` would skip checks, but it seems it behaves the same as `bytes.next()` - i.e. check iterator is not empty, and only advance if it's not. Use `assert_unchecked!` instead to inform compiler that there are definitely the required number of bytes remaining in `bytes` iterator before consuming them. This reduces instruction count considerably, and removes a branch on every byte consumed. https://godbolt.org/z/TWzfK1eKj The mysteries of the compiler! --- crates/oxc_codegen/src/str.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/crates/oxc_codegen/src/str.rs b/crates/oxc_codegen/src/str.rs index af68886a2fbb8..04fb474a24585 100644 --- a/crates/oxc_codegen/src/str.rs +++ b/crates/oxc_codegen/src/str.rs @@ -118,10 +118,13 @@ impl PrintStringState<'_> { /// before calling other methods e.g. `flush`. #[inline] unsafe fn consume_byte_unchecked(&mut self) { - debug_assert!(self.bytes.clone().next().is_some()); + // `assert_unchecked!` produces less instructions than `self.bytes.next().unwrap_unchecked()` + // https://godbolt.org/z/TWzfK1eKj + // SAFETY: Caller guarantees there is a byte to consume in `bytes` iterator, // and that consuming it leaves the iterator on a UTF-8 char boundary. - unsafe { self.bytes.next().unwrap_unchecked() }; + unsafe { assert_unchecked!(!self.bytes.as_slice().is_empty()) }; + self.bytes.next().unwrap(); } /// Advance the `bytes` iterator by `N` bytes. @@ -132,13 +135,16 @@ impl PrintStringState<'_> { /// * After this call, `bytes` iterator must be left on a UTF-8 character boundary. #[inline] unsafe fn consume_bytes_unchecked(&mut self) { - debug_assert!(self.bytes.as_slice().len() >= N); + // `assert_unchecked!` produces many less instructions than + // `for _i in 0..N { self.bytes.next().unwrap_unchecked(); }`. + // The `unwrap` in loop below is required for compact assembly. + // https://godbolt.org/z/TWzfK1eKj + // SAFETY: Caller guarantees there are `N` bytes to consume in `bytes` iterator, // and that consuming them leaves the iterator on a UTF-8 char boundary. - unsafe { - for _i in 0..N { - self.bytes.next().unwrap_unchecked(); - } + unsafe { assert_unchecked!(self.bytes.as_slice().len() >= N) }; + for _i in 0..N { + self.bytes.next().unwrap(); } }