On 13/08/2026 19:22, Iván Ezequiel Rodriguez wrote:
In UTF-8 locales, -w (without --whitespace-delimited=trimmed) used the
slow cut_fields_mb_any path.  Route it through cut_fields_bytesearch
with memchr2 for ASCII blanks plus a linear scan for c32issep
multibyte blanks, with the same semantics as mcel_isblank.

Preserve only truly incomplete UTF-8 tails via
mbrtoc32 == (size_t) -2, so complete characters are not held across
refill (cf. mbbuf_fill responsiveness).  Invalid UTF-8 and
continuation-only input remain field data and always make progress.

Timings on this host (LC_ALL=C.UTF-8, cut -w -f1):

   mostly-ASCII ~20MiB:  ~0.073s -> ~0.018s
   heavy UTF-8  ~136MiB: ~0.67s  -> ~0.41s

Hmm, the implementation looks potentially quadratic to me,
as memchr2() is done for each multi-byte separator found.
This is OK for -f1 as you benchmarked but then gets worse.
I suppose you could cache uni-byte and multi-byte separators
to avoid the rescan?

Testing a pathological case shows a 70x slow down:

  $ { yes $(printf 'a\xe2\x80\x83') | head -n40000 | tr -d '\n'; echo b; } > 
mb.in
  $ time src/cut -w -f999999 mb.in
  real  0m0.541s

  $ git show src | patch -p1 -R
  patching file src/cut.c
  $ make src/cut

  $ time src/cut -w -f999999 mb.in
  real  0m0.007s

cheers,
Padraig




Reply via email to