GitHub

An optimized wc implementation in Zig, 5-20x faster than GNU and BSD wc. zwc achieves this by using a finite-state machine to process UTF-8 text branchlessly, and by implementing data parallelism to distribute the work across multiple CPU cores.

This is not intended as a complete replacement for the GNU or BSD wc programs. It's missing some of the features, like the --max-line-length flag. Additionally, it only supports ASCII and UTF-8 encodings.

This program is based heavily on Robert Graham's wc2 program.

Here is what the core loop looks like:

const table: [State.STATE_MAX][256]u8 = gen_table();
var counts = [_]usize{0} ** State.STATE_MAX;
var state: usize = State.WASSPACE; // initial state
while (true) {
    const b = file.takeByte() catch break;
    state = table[state][b];
    counts[state] += 1;
}

Development

For the simple version of the state machine, see simple.zig.

For the UTF-8 version of the state machine, see dfa.zig.

For the parallel version, see parallel.zig.

Building

This project currently only compiles with the 0.15.2 version of Zig.

# Build the binary into ./zig-out/bin/zwc
zig build -Doptimize=ReleaseFast
# Alternatively, you can use `just`:
just build-exe ~/.local/bin/zwc # build into local path

Benchmarks

Here are some benchmarks from the english and chinese wikipedia title dumps, which are 165MB text files with lots of words and lines. Programs (in order): zwc, BSD wc, GNU wc, Rust uutils/coreutils wc.

Command Mean [ms] Min [ms] Max [ms] Relative
./zwc enwiki-20260301-all-titles 40.8 ± 1.2 39.6 46.8 1.00
wc enwiki-20260301-all-titles 233.5 ± 10.8 227.5 266.8 5.73 ± 0.31
gwc enwiki-20260301-all-titles 274.5 ± 5.9 271.7 291.1 6.74 ± 0.24
uutils-wc enwiki-20260301-all-titles 260.7 ± 11.6 232.9 268.8 6.40 ± 0.34

Same-size file with mostly chinese characters. The -lwm flags tell the programs to count lines, words, and multibyte characters.

Command Mean [ms] Min [ms] Max [ms] Relative
./zwc -lwm zhwiki-latest-all-titles 40.3 ± 1.1 39.3 46.4 1.00
wc -lwm zhwiki-latest-all-titles 832.5 ± 1.4 829.1 834.0 20.64 ± 0.55
gwc -lwm zhwiki-latest-all-titles 702.0 ± 1.6 699.2 704.5 17.41 ± 0.47
uutils-wc -lwm zhwiki-latest-all-titles 285.5 ± 9.1 275.1 295.6 7.08 ± 0.29

See justfile bench_all and bench_all_multibyte.

Read the original on github.com ↗