From 22b4c6d15d884cab2c463c5ede02bf1f168f5373 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Wed, 3 Jun 2026 20:53:16 +0200 Subject: [PATCH] expr: speed up index from O(N*M) to O(N+M) --- src/uu/expr/src/locale_aware.rs | 14 +++++++++++--- src/uucore/src/lib/lib.rs | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/uu/expr/src/locale_aware.rs b/src/uu/expr/src/locale_aware.rs index c8a4e73e3..9bb13e536 100644 --- a/src/uu/expr/src/locale_aware.rs +++ b/src/uu/expr/src/locale_aware.rs @@ -4,6 +4,7 @@ // file that was distributed with this source code. use std::cmp::Ordering; +use std::collections::HashSet; use uucore::{ CharByte, IntoCharByteIterator, @@ -39,15 +40,22 @@ fn index_with_locale( // In the UTF-8 case, we try to decode the strings on the fly. We // compare UTf-8 characters as long as the stream is valid, and // switch to byte comparison when the byte is an invalid sequence. + // Collect the needle chars into a set first so the search is + // O(N + M) rather than O(N * M). + let needles: HashSet = right.iter_char_bytes().collect(); left.iter_char_bytes() - .position(|ch_h| right.iter_char_bytes().any(|ch_n| ch_n == ch_h)) + .position(|ch_h| needles.contains(&ch_h)) .map_or(0, |idx| idx + 1) } UEncoding::Ascii => { // In the default case, we just perform byte-wise comparison on the - // arrays. + // arrays. A 256-entry lookup table keeps this O(N + M). + let mut needles = [false; 256]; + for &b in right { + needles[b as usize] = true; + } left.iter() - .position(|ch_h| right.iter().any(|ch_n| ch_n == ch_h)) + .position(|&ch_h| needles[ch_h as usize]) .map_or(0, |idx| idx + 1) } } diff --git a/src/uucore/src/lib/lib.rs b/src/uucore/src/lib/lib.rs index 1cf69e09d..4dfffed29 100644 --- a/src/uucore/src/lib/lib.rs +++ b/src/uucore/src/lib/lib.rs @@ -601,7 +601,7 @@ macro_rules! prompt_yes( /// Represent either a character or a byte. /// Used to iterate on partially valid UTF-8 data -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum CharByte { Char(char), Byte(u8),