Ben Hoyt
benhoyt.com · Personal blog · on HN since 2007
Ben Hoyt, a software developer, writes about Python, Go, AWK, performance comparisons, security practices and small-scale web design.
What HN saysHN commenters engage with his word-counting benchmarks, one of whom criticizes the problem constraints as weak benchmarking, and with his AWK interpreter and other posts.
64HN people shared it
28linked it in comments
123stories submitted
6.3Kstory points
2 months agolast shared
2007people per year2026
Most-shared posts
- 1Performance comparison: counting words in Python, Go, C++, C, Awk, Forth, Rust9 people · 819 points · first shared 2021 · 303 comments on HN
- 2The small web is beautiful7 people · 132 points · first shared 2021 · 14 comments on HN
- 3Don’t try to sanitize input – escape output5 people · 493 points · first shared 2020 · 280 comments on HN
- 4GoAWK: an AWK interpreter written in Go5 people · 248 points · first shared 2018 · 88 comments on HN
- 5Every dependency you add is a supply chain attack waiting to happen5 people · 9 points · first shared 2026 · discussion on HN
- 6Designing Pythonic Library APIs5 people · 6 points · first shared 2023 · 1 comments on HN
- 7Structural pattern matching in Python 3.104 people · 288 points · first shared 2021 · 147 comments on HN
- 8Using a Markov chain to generate readable nonsense with 20 lines of Python4 people · 234 points · first shared 2023 · 71 comments on HN
- 9Learning Elm by porting a medium-sized web frontend from React (2019)4 people · 106 points · first shared 2019 · 90 comments on HN
- 10Show HN: I use the WordStar Diamond in 20234 people · 8 points · first shared 2023 · discussion on HN
- 11Different approaches to HTTP routing in Go4 people · 6 points · first shared 2020 · discussion on HN
- 12Rob Pike's simple C regex matcher in Go3 people · 292 points · first shared 2022 · 75 comments on HN
- 13Show HN: Pygit – Just enough git to push itself to GitHub3 people · 208 points · first shared 2017 · 23 comments on HN
- 14Optimizing GoAWK with a bytecode compiler and virtual machine3 people · 105 points · first shared 2022 · 23 comments on HN
- 15AWKGo, an Awk-to-Go Compiler3 people · 83 points · first shared 2021 · 6 comments on HN
What HN people wrote when they linked it
Terr_ · 2025-09-08
> Well... ideas are actually encoded (to some degree) in the words in the training data. So when they synthesize new text, they are, to a degree, synthesizing new ideas.
I don't think that follows: Manipulating a (lossy, imperfect) encoding [0] isn't the same as manipulating the thing it was intended to evoke.
If it is true, then... Well, it's not true in the same way anybody is excited about, because it means "synthesizing new ideas" is something we've been able to do for many decades and which you can easily script up right now at home [1].
[0] https://en.wikipedia.org/wiki/Encoding_(semiotics)
[1] https://benhoyt.com/writings/markov-chain/
hilbert42 · 2025-09-03
WordStar isn't that difficult once you master the diamond keystrokes—E,S,D,X—and the keys adjacent to them. In fact, WordStar's control key 'diamond' was very well thought out. After one mastered the sequence which probably took several days one could enter text very quickly and efficiently. I just found this site which provides an excellent explanation:
https://benhoyt.com/writings/wordstar-diamond/
As I mentioned above I ran WordStar on multiple operating systems and I still have it running under an emulator under Windows.
adamgordonbell · 2024-02-15
Just saw this now.
I don't have any great references to be honest. It's not that its a trade-secret, its just that its an area I don't work on.
The AWK book describes how to build you own Make using AWK. You might like that. And an explanation of it and python implementation is found here:
https://benhoyt.com/writings/awk-make/
Hopefully that helps.
benhoyt · 2023-12-01
One of my favourite computer games was written in Turbo Pascal: ZZT, written by Tim Sweeney of Epic Megagames. It was a quircky text-mode game with puzzles, shooting, and so on. It had a built-in game editor that came even with the free shareware version, and it even had a little programming language called ZZT-OOP.
ZZT's original source code was lost. Years later, Adrian Siekierka painstakingly reverse-engineered the original Pascal code till -- when compiled with the original version of Turbo Pascal -- produced a byte-for-byte identical executable. Amazing! Read more:
- https://blog.asie.pl/2020/08/reconstructing-zzt/
- https://news.ycombinator.com/item?id=22609474
- https://benhoyt.com/writings/zzt-in-go/
SleepyMyroslav · 2022-11-26
the state of benchmarking by normal IT people is tragic. If one checks out his 'optimization problem statement' article [1] they can find:
>ASCII: it’s okay to only support ASCII
>Threading: it should run in a single thread on a single machine
>Stdlib: only use the language’s standard library functions.
This is truly 1978 all over again. No flame graphs, no hardware counters, no bottleneck analysis. Using these 'optimizations' for job interviews is questionable at best.
[1] https://benhoyt.com/writings/count-words/
tambourine_man · 2021-08-21
One of the most fun times I ever had coding was implementing a simple but quite fast and reasonably efficient image hash.
Loosely based on this algorithm:
https://benhoyt.com/writings/duplicate-image-detection/
Highly recommended fun exercise.
djhworld · 2019-12-27
If you're hosting a static site on shared infrastructure (e.g. github pages, S3) where access logs are hard to come by, you can achieve some level of statistics gathering using a 1x1 pixel GIF and putting a CDN in front of it, then putting the CDN logs through GoAccess.
EDIT: this was a blog I loosely followed https://benhoyt.com/writings/replacing-google-analytics/ - one detail I forgot to mention is you have to do some post processing on the log files to get them into a format amenable for use by GoAccess etc, but it's not too difficult
cb321 · 2023-09-11
Often whole program generation in a prog.lang (& ecosystem!) that you already know can substitute for a new prog.lang. Python even has eval. You may be interested in: https://github.com/c-blake/bu/blob/main/doc/rp.md
You can actually get pretty far depending upon boundaries with the always implicit command-option language (when launched from the shell language, anyway). For example, Ben's example can be adapted to:
rp -m^\[A-Za-z\] 'echo nr," ",s[1]'
which is only 5 more characters and only 3 more key downs (less SHIFT-ing) than the space-optimized version of his `awk`.
{ key downs are, of course, just a start to a deep rabbit hole on HCI ergonometrics ending in heatmaps, finger reach/strain/keyboard layouts, left-right hand switching dynamics, etc., but they seem the most portable idea. }
Nim is not Python - it is actually a bit more concise while also being statically typed and can be compiled to code which runs as fast as the best C/C++ (at more expense than one usually wants for 1-liner interactive iteration, though unless you need to test on very large data). That said, I find it roughly "as easy" to enter `rp` commands as `awk`.
If doing this in Python tickles your fancy, Ben actually has an interesting on these ideas: https://benhoyt.com/writings/prig/ you might also find interesting.
EDIT: and while I was typing in a sibling @networked mentions a bunch more examples, but I think my comment here remains non-redundant. I'm not sure even one of those…
lucideer · 2022-12-01
> recursively filter all POST/GET input for example). You can do it in the controller with filter_input etc...
This is what many do and it's extremely bad practice. I wrote a pretty detailed comment here on HN explaining this before but can't find it easily now so here's a similar looking article I found instead: https://benhoyt.com/writings/dont-sanitize-do-escape/
it doesn't need to be a part of the framework, I'd like to leave it up to the developers
You're right, "need" is a strong word, it's a suggestion for a useful feature. Leaving it up to developers does in practice tend to lead to insecure code most of the time though: it can sometimes be nice to help developers write better apps.
If you need raw html output the best approach is to batch DOMSanitize it and cache it to be served raw: in these cases it's usually an exception so turning output escaping off for 1 or 2 exceptions isn't a huge ask (and focused the scope of your attack surface area when you're auditing).
voxic11 · 2025-03-18
This is the article I link my developers whenever I see them making this mistake "Don’t try to sanitize input. Escape output." https://benhoyt.com/writings/dont-sanitize-do-escape/
Its been fairly effective at making them realize the fundamental mistake they are making. Quoting the key part:
> The only code that knows what characters are dangerous is the code that’s outputting in a given context.
> So the better approach is to store whatever name the user enters verbatim, and then have the template system HTML-escape when outputting HTML, or properly escape JSON when outputting JSON and JavaScript.
> And of course use your SQL engine’s parameterized query features so it properly escapes variables when building SQL
MaxBarraclough · 2024-11-22
> Very fast (faster than naive assembler)
Every Forth that uses conventional threaded-code interpretation pays a considerable performance penalty, execution times are likely to be very roughly quadruple the equivalent assembly. [0]
Forth's runtime performance can be competitive with C if 'proper' compilation is performed, though. [1]
[0] https://benhoyt.com/writings/count-words/
[1] (.fth file with their results in comments) http://www.mpeforth.com/arena/benchmrk.fth
veeblevee · 2024-08-28
Also sometimes called the small web. See The small web is beautiful by Ben Hoyt https://benhoyt.com/writings/the-small-web-is-beautiful
Thaxll · 2024-06-01
I've seen Go code faster than Rust one, for example there was an interesting article years ago about counting words in a file:
https://benhoyt.com/writings/count-words/
Beltalowda · 2024-03-03
How did you generate the timings on: https://benhoyt.com/images/go-1brc-profile-r9-source.png ?
simonw · 2024-02-13
Sounds like you might be interested in the Tigris preview:
- https://www.tigrisdata.com/
- https://benhoyt.com/writings/flyio-and-tigris/ (discussed here: https://news.ycombinator.com/item?id=39360870)
- https://fly.io/docs/reference/tigris/
elicksaur · 2024-02-09
fwiw Python also has pattern matching: https://benhoyt.com/writings/python-pattern-matching/
ibitto · 2023-05-13
Two more Python implementations are mentioned in build-your-own-x [0].
- https://wyag.thb.lt
- https://benhoyt.com/writings/pygit/
[0]: https://github.com/codecrafters-io/build-your-own-x#build-your-own-git
pyjarrett · 2022-11-06
> how could this ever be proven to never go out of bounds?
I've done this in Ada/SPARK.
My simple_regex implementation of Rob Pike's algorithm [1] based on this blog post [2], is proved not to crash on overflow or bounds checks.
[1]: https://github.com/pyjarrett/simple_regex
[2]: https://benhoyt.com/writings/rob-pike-regex/
hddqsb · 2022-06-05
To improve performance, consider using `export LC_ALL=C` (credit: https://benhoyt.com/writings/count-words/). But note that it sorts uppercase and lowercase separately, and doesn't handle Unicode well.
stevekemp · 2022-03-01
Funny you should say that .. this piece from the same author describes just that:
https://benhoyt.com/writings/awkgo/
makapuf · 2022-02-27
Sure, go itself didnt build it from scratch - rewriting your implementation each time you change your language might grow tiresome fast, but I was referring that toy/minimal implementations exist : https://benhoyt.com/writings/mugo/
jidiculous · 2021-09-19
> but the performance profiles & characteristics that we must know about in order to make a choice on which tool to use. And it shouldn't be that each user has to figure it out on their own, dig into PR's or whatever.
That's an interesting take – I like the idea of a catalog of standard tasks with implementations in several languages as well as their performance characteristics. I suppose Rosetta Code gets the ball rolling with this, but it's missing some performance metrics. It reminds me of Ben Hoyt's piece[1] on counting unique words in the KJV Bible in different languages.
1: https://benhoyt.com/writings/count-words/
gryfft · 2020-09-04
Little enrages me more, especially when the forbidden special characters betray a shockingly backwards mitigation for injection attacks.
[1] https://benhoyt.com/writings/dont-sanitize-do-escape/
hosh · 2024-10-14
There is a whole lot more to this than just whether content creators or publishes should get paid, and whether there should be ad blockers (and whether they get paid).
There are people who have been fed up by this because they remembered how the web was like in the late 90s, before social media pushes became the dominant experience. People have formulated ideas around the Small Web (https://benhoyt.com/writings/the-small-web-is-beautiful/), or even opted out of the browser ecosystem entirely with Gemini (https://geminiprotocol.net/) or keep the torch burning for Gopher (https://hackaday.com/2021/09/28/gopher-the-competing-standard-to-www-i…
From there, it is also a short hop and skip away to folks working on local-first (https://localfirstweb.dev/), decentralization, collapse computing (https://100r.co/site/philosophy.html and http://collapseos.org/)
sargstuff · 2024-02-22
Using C would tie the run-time/compiled implimentation to specific set of platforms/hardware. aka each hardware platform would have it's own specific compiled C quirks/issues to deal with. aka big endian / little endian; 16/32 bit; etc.
A virutal machine is typically what is used when not targeting an actual machine/hardware. aka runtime environment.
Transpiling the language to java or webassembly would provide for wider range of hardware/platform support without requiring specific knowlege compiled C platform quirks -- big endian/little endian machine. Although, transpiling to awk with system() & named pipes/netcat, perl, javascript, and/or creating an excell 16 bit cpu[7]/virtual pc could work too.
"1st class"[0] concept implies there are no restrictions on where given language construct/concept can be used. for example: which side of the assignment operator a programming language concept/construct can be used.
"type inference"[1] is typically an interpreted/virtual machine language feature. aka C++ run time type inference (rtti) is done via instance of a virtual machine.
namespace / scoping is important aspect of modularity / avoiding code coloring issues / automatic translation between formats / 'reactivity'[2]
XL[3], oils/ysh[4], unicorn[5]/unicorn.js[6], awkgo[8], pawk[9] might be of interest.
Would suggest using ' JS/Ocaml/Rust' implimented/running under python (and/or bindings to ocaml/rust).
A related example/demo of this approach would be awk running…
wormius · 2024-05-25
Google is your friend: https://benhoyt.com/writings/the-small-web-is-beautiful/ https://ar.al/2020/08/07/what-is-the-small-web/ https://blog.kagi.com/small-web
Another related term: https://en.wikipedia.org/wiki/IndieWeb
see also: https://en.wikipedia.org/wiki/Gemini_(protocol) (NOT web, but similar in spirit - an extended "Gopher"-like protocol)
jonjacky · 2023-12-20
Some other git-in-python projects include Dulwich [1], gittle [2], wyag [3], pygit [4], and zit [5]
1. https://www.samba.org/~jelmer/dulwich/docs/
2. https://github.com/FriendCode/gittle
3. https://wyag.thb.lt/
4. https://benhoyt.com/writings/pygit/
5. https://github.com/jmou/zit
I'm not listing these to criticize the poster's project. It is interesting to compare these projects. git-like programs form a whole category which provides opportunities to experiment with design ideas and programming style.
In this same spirit, there are also several (many?) vi-in-python projects.
azhenley · 2021-05-27
Cover topics around software development, math, programming languages, and academia:
http://stuffwithstuff.com/
https://ericlippert.com/
http://thume.ca/archive.html
https://medium.com/@mdwdotla
https://faculty.washington.edu/ajko/posts
https://computinged.wordpress.com/
https://blog.acolyer.org/
https://blog.sigplan.org/blog/
https://blog.paranoidcoding.com/
https://blog.regehr.org/
https://eli.thegreenplace.net/
https://benhoyt.com/writings/
https://www.hillelwayne.com/post/
https://web.eecs.utk.edu/~azh/blog.html
https://www.johndcook.com/blog/
https://blog.stephenmarz.com/