From 8c8da78cf8e28c8a067e056b14a2f88117e4c0c6 Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi Date: Fri, 22 Nov 2024 15:33:13 -0600 Subject: [PATCH] Speed up get_case_fold() 5x Using `c.is_uppercase()` instead of getting the iterator and checking if the first (and only) lowercase letter of the sequence is the same as the original input is 5-8x faster (measured via criterion against `/usr/share/dict/words`). (Additional benefit of forcibly inlining the now iterator-based comparison not taken into account; this necessitated changing from a closure to a local function as the inline attribute on closures is not yet supported with the stable compiler toolchain.) --- src/wcstringutil.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/wcstringutil.rs b/src/wcstringutil.rs index c4a39e652..88728156b 100644 --- a/src/wcstringutil.rs +++ b/src/wcstringutil.rs @@ -175,14 +175,14 @@ impl StringFuzzyMatch { ) -> Option { // Helper to lazily compute if case insensitive matches should use icase or smartcase. // Use icase if the input contains any uppercase characters, smartcase otherwise. - let get_case_fold = || { - for c in string.chars() { - if c.to_lowercase().next().unwrap() != c { - return CaseSensitivity::Insensitive; - } + #[inline(always)] + fn get_case_fold(s: &widestring::Utf32Str) -> CaseSensitivity { + if s.chars().any(|c| c.is_uppercase()) { + CaseSensitivity::Insensitive + } else { + CaseSensitivity::Smart } - CaseSensitivity::Smart - }; + } // A string cannot fuzzy match against a shorter string. if string.len() > match_against.len() { @@ -207,12 +207,18 @@ impl StringFuzzyMatch { // exact icase if wcscasecmp(string, match_against).is_eq() { - return Some(StringFuzzyMatch::new(ContainType::Exact, get_case_fold())); + return Some(StringFuzzyMatch::new( + ContainType::Exact, + get_case_fold(string), + )); } // prefix icase if string_prefixes_string_case_insensitive(string, match_against) { - return Some(StringFuzzyMatch::new(ContainType::Prefix, get_case_fold())); + return Some(StringFuzzyMatch::new( + ContainType::Prefix, + get_case_fold(string), + )); } // If anchor_start is set, this is as far as we go. @@ -234,7 +240,10 @@ impl StringFuzzyMatch { // substr icase if ifind(match_against, string, true /* fuzzy */).is_some() { - return Some(StringFuzzyMatch::new(ContainType::Substr, get_case_fold())); + return Some(StringFuzzyMatch::new( + ContainType::Substr, + get_case_fold(string), + )); } // subseq samecase