SIMD kernels (AVX-512/AVX-2/SSE2, runtime-dispatched) counting a single pass over mmap'd files, split across cores past 8 MiB, with exact GNU oracle parity (NBSP included, glibc's decoder fixed, the whole -m path mirrored so counts agree at every boundary). Result: 1ms vs 2ms at 1M lines, 8-9ms vs 22-24ms at 10M. Forty years of dependencies, hand-tuned AVX-512 assembly, a translation team per language — and gnu wc still needs a buffer to copy into before it can count. We mapped the file and just counted. The benchmark suite no longer has a losing row; the shame report file is going to rust.
4.0 KiB
4.0 KiB
fastwc Style Guide
The style is the law. GNU wc can afford to look like a committee designed it — it was. We're one file, one purpose, one opinion.
The language
- C99 with POSIX.
_POSIX_C_SOURCE 200809L. We target the standard, not a compiler vendor's mood. - Zero warnings with
-Wall -Wextra. A warning is a bug you haven't fixed yet. Fix it. - No compiler-specific extensions unless they're guarded and the
benchmark gets faster because of it.
__builtin_popcountllis the one exception — it's the price of admission on every compiler that matters, and the benchmark proves it.
Format
- 4 spaces. Not tabs, not 8 spaces. GNU uses tabs because GNU was written in 1985 by people who had strong opinions about typewriters.
- 80 columns. If your line is longer, your idea is longer than it needs to be.
- Braces on the next line (Allman). Everywhere. Functions, blocks, switch cases. Consistency is the only religion here, and we're devout.
- Snake case for everything.
count_stream,ws_tab,nread. No CamelCase — that's for languages that need help knowing what a word is.
Structure
- One file:
src/main.c. See CONTRIBUTING.md rule 6. This is not a suggestion. - Everything is
static. The binary exports nothing. We're not a library, we're a verdict. - Types end in
_t.counts_t, and not much else. GNU has a type for everything and a committee to name it. We have counts, and we count. - No globals except what's truly process-wide.
flagsandws_tablive at file scope because they're the program's identity. Everything else gets passed around like it's hot.
The hot path
count_stream(), count_newlines(), count_words(), and the SIMD
kernels (count_lw_avx512, count_lw_avx2, count_lw_sse2) are the
product. The rest of the file is just the packaging.
- Fixed stride. No per-token function calls. No
isspace()in a loop — that's what the lookup table is for. - No allocation, no locks, no syscalls in the counting loop. The
kernels are pure; parallel slices need no locks. The
fread(or the singlemmap) is the only syscall, and it's not yours to add to. - Branchless where it costs nothing. A predictable branch is fine; a mispredicted one is a lie you told the CPU.
- Regular files are mapped, not streamed. The kernel hands us the
pages; we count them, split across cores for anything past 8 MiB.
Stdin and odd files fall back to the
static, 128 KiB buffer that never grows.
Counts
long longfor everything that counts. Files can be bigger than your opinions. Signed, because overflow should scream, not wrap.- Lines are
'\n's. Not "lines of text," not "records." A file without a trailing newline has fewer newlines than it has lines, and that's correct. GNU agrees with us on this one, so it must be right. - Words are whitespace-delimited runs. The lookup table decides what whitespace is; the popcount decides how many words; you don't get an opinion.
Errors
fastwc: <file>: <message>on stderr, and keep going. GNU wc fails gracefully across multiple files, and we'll credit them that one thing. Then we'll be faster at it.- Exit 1 if anything failed, 0 otherwise. No drama, no
EXIT_FAILUREpoetry.
Comments
- Only when the code can't speak for itself. The SWAR newline
counter in
count_newlines()gets a comment because(x ^ nl) & clis a sentence in a language you don't speak yet.i++does not get a comment. - No commented-out code. The dead don't get to live in the file.
- No TODO without a date. A TODO without a date is a promise you plan to break.
What the style is not
- It is not GNU's style. GNU's style was written by a committee, ratified by a foundation, and translated into fourteen languages.
- It is not "whatever your editor defaults to." Your editor has opinions. So do we. Ours are right.
- It is not negotiable in review. If a PR violates the style, the PR is a rewrite request with extra steps.