41 Commits
Author SHA1 Message Date
Sylvestre Ledru 56d774f576 test: cover slow-path modes that literal tests no longer reach
The buffer-at-a-time fast path now serves the literal patterns that the
existing -l/-L/-q and binary tests used, leaving the line-at-a-time
engine's equivalents uncovered. Add bracket-class (non-literal) tests
for -l/-L/-q and binary handling (notice, -a text, without-match bail,
and the finalize-time notice), plus a fast-path test for a NUL that is
only discovered after a line was already printed.

No dead code was found: the remaining uncovered lines are writer I/O
error-propagation arms and pre-existing filesystem error handlers.
0.1.0
2026-06-04 22:24:27 +02:00
Sylvestre Ledru 28186e9ec3 perf: buffer-at-a-time search for literal patterns
Literal searches were ~50-70x slower than GNU grep because every line
paid per-line costs (terminator scan, NUL scan, dispatch) even when a
buffer held no match. Add a buffer-at-a-time driver that scans whole
chunks with a substring searcher and only locates line boundaries
around the matches it finds; a chunk with no match costs a single
vectorized sweep and no per-line work.

The driver activates only for plain ASCII literal patterns (case
sensitive, no metacharacters) in the simpler output modes: -c, -l, -L,
-q, and plain line printing with -n/-b/filename/-m. Anything needing
match positions, context, inversion, color, or special binary handling
falls back to the unchanged line-at-a-time path. Output stays
byte-identical to that path, including binary/invalid-UTF-8 behavior.

- line_buffer: read_chunk() yields the largest span of complete lines.
- matcher: expose per-pattern memmem searchers when every pattern is a
  plain literal (plain_literal()).
- searcher: eligible_for_fast_path(), fast_locate(), fast_print().

All scanning rides on the memchr crate (SIMD memchr/memrchr/memmem).
Unit tests for read_chunk and plain_literal; integration tests for
prefixes, -m, and multi-chunk line-number correctness.

Benchmarks (31 MB corpus) vs prior release:
  -F (no match):  232ms -> 15ms  (15.9x; now faster than GNU)
  -c literal:     229ms -> 15ms  (15.2x)
  plain print:    248ms -> 18ms  (13.5x)
Regex and -i paths are unchanged (still the line-at-a-time engine).
2026-06-04 22:24:27 +02:00
rifatx f4798cb6d0 fix -l and -L to be mutually exclusive so that last one wins (#30) 2026-06-04 22:14:12 +02:00
Sylvestre Ledru 4e6823a8b3 Add installation section to README (#29) 2026-06-03 17:56:23 +02:00
Sylvestre Ledru b0700b1d78 Merge pull request #21 from oech3/pub
GnuTests: publish binary from main
latest-commit
2026-06-02 21:04:50 +02:00
oech3 bc416c6d8b GnuTests: publish binary from main 2026-06-03 00:05:24 +09:00
Sylvestre Ledru c614a57a05 Merge pull request #17 from uutils/e2e-bench-only
E2e bench only
2026-05-31 11:17:38 +02:00
Sylvestre Ledru 6e6db248f1 bench: add e2e benchmarks for the grep tldr invocations
Cover the real-world grep usage shapes from the tldr page end-to-end
through uumain over a shared multi-MB corpus (plus a directory with a
binary file for -rI):

  search pattern, -F fixed string, -rI recursive ignoring binary,
  -C 3 context, -Hn --color=always, -o only-matching, -v invert,
  -Ei extended + ignore-case.

Kept alongside the pure-scan throughput benches (literal vs regex, no
match). A rare marker keeps matched output small so the full-file scan
dominates the timing.
2026-05-31 11:10:11 +02:00
Sylvestre Ledru b5816820ed bench: end-to-end search throughput only
Replace the matcher micro-benchmarks with a single end-to-end 'search'
group driven through uumain over a multi-megabyte file: a literal
pattern (which a buffer-at-a-time searcher can accelerate) and an
extended-regex control (which cannot). Matching pre-split lines in
isolation cannot reveal how the searcher feeds data to the matcher;
this does.
2026-05-31 11:05:28 +02:00
Sylvestre Ledru ede1676d1a Merge pull request #15 from uutils/bench-literal-throughput
bench: end-to-end search throughput via uumain
2026-05-31 10:55:17 +02:00
Sylvestre Ledru b46a86d48a bench: end-to-end search throughput via uumain
The existing match/throughput benches call Matcher::match_line on
pre-split lines, so they only measure matching in isolation and cannot
observe how the searcher feeds data to the matcher. Add a 'search'
group that drives the whole pipeline through uumain over a multi-MB
file: a literal pattern (which a buffer-at-a-time searcher can speed
up) and an extended-regex control (which it cannot). Uses -q with a
non-matching pattern for a silent full-file scan.
2026-05-31 10:41:52 +02:00
Sylvestre Ledru b0164440e3 Merge pull request #14 from uutils/fix
Add Default impl for GlobSet to satisfy clippy
2026-05-31 10:34:25 +02:00
Sylvestre Ledru 96762f26ca Add Default impl for GlobSet to satisfy clippy 2026-05-31 10:18:32 +02:00
Sylvestre Ledru c8dfef6563 Add pre-commit configuration 2026-05-31 10:11:57 +02:00
Sylvestre Ledru ddac723054 Merge pull request #13 from uutils/codspeed-wizard-1780213675759
Add CodSpeed performance benchmarks
2026-05-31 10:11:23 +02:00
codspeed-hq[bot] 079619ee44 Add CodSpeed performance benchmarks 2026-05-31 07:59:22 +00:00
Sylvestre Ledru 2a6a3aba7e Add note about performance improvements needed 2026-05-30 19:25:27 +02:00
Sylvestre Ledru 98e6bb6f53 Merge pull request #10 from uutils/improv-cov
Improve the code coverage
2026-05-30 14:25:50 +02:00
Sylvestre Ledru da0ada8a37 test: use platform-specific expected message for nonexistent-file error 2026-05-30 11:33:47 +02:00
Sylvestre Ledru fcf46d8f56 test: cover -D skip on an explicit special-file argument 2026-05-30 11:28:04 +02:00
Sylvestre Ledru 55cb643545 test: cover strip_dot_prefix for implicit-cwd recursive search 2026-05-30 11:28:04 +02:00
Sylvestre Ledru 89aec4a45a test: cover -T line-number width on the file (not stdin) path 2026-05-30 11:28:03 +02:00
Sylvestre Ledru 6c5b7dc9e3 test: cover -L listing when the pattern matches one file 2026-05-30 11:28:03 +02:00
Sylvestre Ledru ff918e4a63 grep: strip trailing (os error N) from file error messages to match GNU (#6) 2026-05-29 22:24:20 +02:00
Sylvestre Ledru c50c0458cb fix: accept repeated options like GNU grep (#2)
GNU grep tolerates options given more than once (boolean flags are
idempotent, value options take the last occurrence), but clap rejected
them with "cannot be used multiple times" (exit 2). Set
args_override_self(true) so clap replaces rather than errors; args with
ArgAction::Append (-e/-f/--include/--exclude) still accumulate.

Found by the differential fuzzer (e.g. `grep -e .* -E -n -o -n -x`).

Add a regression test covering repeated booleans, repeated value options
(last wins), and that -e still accumulates patterns.
2026-05-29 22:21:27 +02:00