bench: rub it in — monsters, stdin wins, busybox retired

Suites split into benchmarks/files/{lines,words} and
benchmarks/stdin/piping, with the monsters bolted onto the lines suite:
100M lines raced against coreutils (~2x win), 1B lines solo (~6-8s,
11 GB in one pass). Stdin redirects from regular files are now mmap'd
in count_stream, so the stdin suite wins too — up to 12.00x on words.

The ratio column now reports how many times faster fastwc is, not how
much of GNU's time it used. busybox was removed from the suite: it
stopped being a challenge and started being a participation trophy.
GNU wc's lone win — 1M lines by one millisecond on hand-tuned AVX-512
assembly — is now a historical footnote, and the README says so.
This commit is contained in:
2026-08-29 15:52:24 -04:00
parent ff465e981b
commit 6aa461f053
13 changed files with 362 additions and 177 deletions
+29 -18
View File
@@ -336,6 +336,8 @@ static lw_t count_lw_scalar(const unsigned char *s, size_t n, int *prev_ws,
static count_lw_fn count_lw = count_lw_scalar; /* chosen by pick_kernel() */
static void count_mapped(const unsigned char *p, size_t n, counts_t *c);
#if defined(__x86_64__) || defined(__i386__)
static count_lw_fn pick_kernel(void)
{
@@ -528,6 +530,28 @@ static void count_stream(FILE *fp, counts_t *c)
return;
}
/* Regular file — named or a stdin redirect — map instead of
* streaming: no copy, and the count can be split across cores. */
struct stat st;
if (fstat(fileno(fp), &st) == 0 && S_ISREG(st.st_mode) && st.st_size > 0)
{
if (flags == F_BYTES)
{ /* GNU wc does not read the file either */
c->bytes = (long long)st.st_size;
return;
}
void *m = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_PRIVATE,
fileno(fp), 0);
if (m != MAP_FAILED)
{
count_mapped((const unsigned char *)m, (size_t)st.st_size, c);
munmap(m, (size_t)st.st_size);
if (ferror(fp))
c->ok = 0;
return;
}
}
for (;;)
{
nread = fread(buf, 1, sizeof buf, fp); /* NOLINT: EOF-state FP */
@@ -675,29 +699,16 @@ static void count_file(const char *path, counts_t *c)
return;
}
/* Regular files: map instead of streaming - no copy, and the count
* can be split across cores. Falls back to streaming on any hitch. */
struct stat st;
if (fstat(fileno(fp), &st) == 0 && S_ISREG(st.st_mode))
/* count_stream maps regular files itself; -c alone skips reading */
if (flags == F_BYTES)
{
if (flags == F_BYTES)
{ /* GNU wc does not read the file either */
struct stat st;
if (fstat(fileno(fp), &st) == 0 && S_ISREG(st.st_mode))
{
c->bytes = (long long)st.st_size;
fclose(fp);
return;
}
if (!(flags & F_CHARS) && st.st_size > 0)
{
void *m = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_PRIVATE,
fileno(fp), 0);
if (m != MAP_FAILED)
{
count_mapped((const unsigned char *)m, (size_t)st.st_size, c);
munmap(m, (size_t)st.st_size);
fclose(fp);
return;
}
}
}
count_stream(fp, c);