Files
fastwc/CONTRIBUTING.md
T
huntedbytheirs c4d4f0b713 first: setup
setting up repo.
2026-08-29 13:48:15 -04:00

5.0 KiB

Contributing to fastwc

We're building the word counter GNU wc is still trying to be after forty years. If that sounds like your kind of project, keep reading.

The rules

These aren't guidelines. They're the deal.

1. The benchmark is the contract

./benchmarks/bench-coreutils.sh must pass. Not "mostly pass." Not "pass on your machine." Pass.

The moment fastwc is slower than GNU wc — or disagrees with it on a single count — your change does not ship. We did not spend this much effort being faster than a forty-year-old dependency museum just so you could add a strlen() in the hot loop.

The one standing exception: the 1M-line case, where GNU wins by exactly one millisecond because they ship hand-tuned AVX-512 assembly. Closing that gap is the project's open goal, not your excuse to be slower anywhere else.

2. C99, or don't bother

We compile with -Wall -Wextra and zero warnings. Zero. If the compiler is complaining, the compiler is right and you are wrong. We target C99 with POSIX extensions, not whatever your compiler vendor's imagination happens to ship this quarter.

3. No new dependencies. Ever.

The C standard library is the only thing we trust. No gettext. No gnulib. No libutf8pro with its own translation team. GNU wc needs a build system the size of a small country to count newlines. We need cc.

If your feature needs a library, the feature is too big. Make the feature smaller.

4. The hot path is sacred

count_stream(), count_newlines(), and count_words() in src/main.c are the entire point of this project. You may touch them only if ./benchmarks/bench-coreutils.sh still passes afterward. Rules for the counting loops:

  • fixed stride, no per-token function calls
  • no allocation, no locking, no syscalls — the read is the only syscall
  • branchless where it costs nothing; lookup tables are the foundation, not a hack
  • if you make it "clearer" but 2x slower, it's not clearer, it's worse

5. Never suppress the truth

No casts to silence warnings. No -Wno-* flags to make the noise go away. No void* where a real type exists. If the type system is fighting you, you're fighting the design. Fix the design.

6. The codebase is one file. Keep it that way.

src/main.c is one file and it will stay one file. GNU wc needs forty-two translation units and a build system with its own mailing list. We have one file and we can read all of it in one sitting. If your feature needs a new file, your feature is over-engineered.

7. Tests are the benchmarks

There is no separate test suite, because the benchmark is the test suite — it checks correctness against GNU wc (the only oracle around, and it's wrong often enough to keep us humble) and speed in the same breath. Add a flag? It gets benchmarked. Change the counting? It gets benchmarked. The fail-fast scripts in benchmarks/ are your tests, and all of them must pass before you open a PR.

8. No AI slop

If it looks like ChatGPT wrote it, it gets rejected. We can tell. Write code like a human who's been doing this for a decade and is tired of GNU's excuses.

How to contribute

Pick something

Good first issues:

  • Closing the 1M-line AVX-512 gap (the only loss on the board)
  • Benchmark case coverage for -m and multiple files
  • bench-busybox.sh CI on a machine that actually has busybox

Ambitious issues:

  • A word counter that doesn't just tie GNU — it embarrasses it
  • Bigger SWAR chunks, wider strides, less patience

Send a PR

  1. Fork the repo
  2. Create a branch: feat/my-thing or fix/my-bug
  3. Write code that follows the rules above
  4. Run ./benchmarks/test-all.sh — everything must pass
  5. Open a PR against main

PR requirements

  • Build must pass with zero warnings: make && make release
  • Benchmarks must pass: ./benchmarks/test-all.sh
  • Follow STYLEGUIDE.md. The style is the law.
  • No commented-out code. No dead code. No TODO without a date.
  • Commit messages in imperative: Count newlines in 8-byte strides not Added newline counting optimization

What we won't merge

  • Anything slower than GNU wc. We didn't come this far to tie.
  • Dependencies. If it needs a library, it needs to not need a library.
  • GNU-style bloat. Long options with help strings in fourteen languages. Translation infrastructure. "Enterprise" anything. This is a word counter, not a CRM.
  • Abstract nonsense. Three layers of indirection to add a feature means the feature is too complicated. GNU wc is what happens when you let abstractions win.
  • AI slop. See rule 8.

Communication

We don't have a Discord. We don't have a forum. We don't have a mailing list with a code of conduct and a weekly digest. Open an issue. Write a clear title, a reproduction case, and what you expected. We'll respond when we respond.

If you want to propose a major feature, open an issue first. Surprise PRs that rewrite the counting loops get closed without review — the benchmark is the referee, and it doesn't know you.


fastwc is 0.1.0. Everything is subject to change except the rules above.