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:
+29
-18
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user