Huntclaw: A fast search-and-replace utility

PROJECT NAME: huntclaw


I’d like to introduce huntclaw, a search-and-replace utility written in Zig that turned out to be faster than sd (written in Rust) and the standard GNU utilities.

there’s a fairly simple explanation for this high speed: the lack of a regex/regex engine and a focus on speed itself. Note that searching is also very fast because of SIMD two-byte prefiltering

In the photo I’ve attached above, you can see the benchmark: huntclaw vs. other utils. You can run them yourself using the ‘huntclaw_bench.py’ file in repo (or on your own tests). All the stats are shown in no regex mode for everyone
the benchmark also shows that rg and grep is faster at sparse searches, though the gap isn’t that big (20ms-9ms and 55ms-1619ms)

version now: v0.8. Right now, I plan to add at least experimental regex support to the v1.0 release, with optimizations, of course

huntclaw on GitHub: GitHub - tigerlang/huntclaw: huntclaw - a very fast find-and-replace utility · GitHub

Supported Zig versions

I’m tested and wrote it in Zig 0.16, so 0.16.

LLM disclosure

I used an LLM to help with optimizations, difficult problems that I didn’t have enough experience to solve on my own and file ‘huntclaw_bench.py’ (tbh, I don’t have time to create benchmarks in py)

6 Likes

Benchmark with the same output volume - either both printing or both silent. Comparing a printing ripgrep against a silent huntclaw isn’t measuring search speed.
Also, --count-matches in ripgrep does line-oriented per-match work. rg --null-data --count-matches is probably closer to what huntclaw actually does, since it drops line semantics. This changes the performance comparison significantly on my box.

4 Likes

Interesting project, especially since I try to build something similar (but less complex) for one of my programms.

One question: you selected the llm tag but didn’t mention for what you’ve used LLMs. I’m just curious which parts were LLM created regarding the architecture, since at the moment I think about the best approach for my project.

1 Like

Thank you for this reply,

I used an LLM to help with optimizations, difficult problems that I didn’t have enough experience to solve on my own and file ‘huntclaw_bench.py’ (tbh, I don’t have time to create benchmarks in py)

1 Like

Hey, I was actually looking at grep and buffering strategies recently and I had just one problem testing your implementation in that it attempts to read the whole file at once rather than streaming the files in chunks, and as a result it simply fails to process those files. It’s probably reasonable as reading such large files is quite niche, and the max file size in your program is already very generous, but the error message:

huntclaw: cannot read ./embigged: StreamTooLong

could be a bit more explicit. How large was the file and how large is the limit?

1 Like

With the updated benchmark, your solution doesn’t seem as attractive as the original post. Maybe you would be liking to edit the op, plus mentioning LLM usage? It’s not immutable.

(I can’t edit this post idk, i’ve tried)