From 81e33a37010f57c1474c493275d125a781f4a9ce Mon Sep 17 00:00:00 2001 From: overlookmotel Date: Tue, 30 Jan 2024 10:49:31 +0000 Subject: [PATCH] perf(parser): faster offset calculation (#2215) A faster way to calculate offset in the lexer. This only moves the needle because it's on the hottest path in the lexer - `Lexer::offset` is called for every token in `Lexer::read_next_token`. --- crates/oxc_parser/src/lexer/mod.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/oxc_parser/src/lexer/mod.rs b/crates/oxc_parser/src/lexer/mod.rs index ec6d50fea..3cb8f585e 100644 --- a/crates/oxc_parser/src/lexer/mod.rs +++ b/crates/oxc_parser/src/lexer/mod.rs @@ -252,7 +252,14 @@ impl<'a> Lexer<'a> { #[inline] #[allow(clippy::cast_possible_truncation)] fn offset(&self) -> u32 { - (self.source.len() - self.current.chars.as_str().len()) as u32 + // Offset = current position of `chars` relative to start of `source`. + // Previously was `self.source.len() - self.current.chars.as_str().len()`, + // but that was slower because `std::str::Chars` internally is a current pointer + end pointer, + // whereas `&str` internally is a start pointer and len. + // So comparing `len()` of the two requires an extra memory read, and addition operation. + // https://godbolt.org/z/v46MWddTM + // This function is on hot path, so saving even a single instruction makes a measurable difference. + (self.current.chars.as_str().as_ptr() as usize - self.source.as_ptr() as usize) as u32 } /// Get the current unterminated token range