L
Laurence Tratt
tratt.net · Personal blog · on HN since 2008
Laurence Tratt, a computer science researcher, writes about programming language implementation, VMs, parsing, and benchmarking methodology.
What HN saysHN links his posts on parsing being an unsolved problem and on why minimum times mislead in benchmarking, both cited as clear explanations.
130HN people shared it
60linked it in comments
229stories submitted
6.6Kstory points
4 months agolast shared
2008people per year2026
Most-shared posts
- 1Fast enough VMs in fast enough time8 people · 229 points · first shared 2012 · 33 comments on HN
- 2Fast Enough VMs in Fast Enough Time (2013)6 people · 54 points · first shared 2013 · 14 comments on HN
- 3The Bootstrapped Compiler and the Damage Done (2013)6 people · 20 points · first shared 2013 · 2 comments on HN
- 4Why Aren’t More Users More Happy With Our VMs? Part 1 (2018)5 people · 267 points · first shared 2018 · 88 comments on HN
- 5RPython-Based VMs: Fast Enough in Fast Enough Time5 people · 100 points · first shared 2017 · 17 comments on HN
- 6Minimum Times Tend to Mislead When Benchmarking5 people · 61 points · first shared 2019 · 13 comments on HN
- 7Parsing: The Solved Problem That Isn't5 people · 9 points · first shared 2016 · discussion on HN
- 8How can C Programs be so Reliable?4 people · 367 points · first shared 2008 · 152 comments on HN
- 9Practising Programming4 people · 236 points · first shared 2022 · 41 comments on HN
- 10Some Reflections on Writing Unix Daemon4 people · 110 points · first shared 2024 · 37 comments on HN
- 11More evidence for problems in VM warmup4 people · 93 points · first shared 2022 · 34 comments on HN
- 12An editor for composed programs4 people · 91 points · first shared 2014 · 35 comments on HN
- 13Rust's Two Kinds of 'Assert' Make for Better Code4 people · 61 points · first shared 2023 · 85 comments on HN
- 14Dynamically Typed Languages (2009)4 people · 57 points · first shared 2014 · 56 comments on HN
- 15Two Stories for “What Is Cheri?”4 people · 8 points · first shared 2023 · discussion on HN
What HN people wrote when they linked it
hyperpape · 2024-01-04
There are good reasons to discard the best runs. If you think of your system as having predictable behavior that's slowed down by background processing happening on the machine, it might make sense to use the best run. But if there are any intrinsic sources of non-determinism in the program (and it's far more likely than you might think), taking the best time is likely to be unrepresentative.
https://tratt.net/laurie/blog/2019/minimum_times_tend_to_mislead_when_… is a good piece on the subject.
bear8642 · 2021-05-27
http://www.commandlinefanatic.com/cgi-bin/showpage.cgi?page=home is good deep dive into various topics. Enjoy the gzip explaination
Matt might's 'blog' https://matt.might.net/articles/ is good read about various functional ideas and others
https://aphyr.com/posts/342-typing-the-technical-interview funny post about how complicated balancing a binary tree could be
https://tratt.net/laurie/blog/archive.html some intersting posts about various aspects of programming language tools
bollu · 2020-07-15
Awesome. I love good research into parsing, since parsing is famously "the solved problem that isn't": https://tratt.net/laurie/blog/entries/parsing_the_solved_problem_that_…
I hope to study this paper well (which is by the author of the above post) and understand what their algorithm is. I feel that good error messages make or break a language.
Here is the arxiv link of the same paper: https://arxiv.org/pdf/1804.07133.pdf
dzamlo · 2019-10-14
[This article](https://tratt.net/laurie/blog/entries/minimum_times_tend_to_mislead_wh… explaib why using the minimum time may not be a so great idea.
sitkack · 2014-09-13
This is great on many levels.
1. They are using MPS [0] from JetBrains, a system for constructing tooling around Domain Specific Languages.
2. Markus Voelter is a huge proponent of DSLs and a very level headed fellow. Loved his interview with Laurence Tratt [1] about compile time metaprogramming [2].
This brings benefits of Ada and Lisp with a modern JetBrains style IDE while targeting a C99 runtime. I think being able to sculpt the language to the project can greatly compact the abstraction distance from the problem domain to the code.
[0] http://www.jetbrains.com/mps/
[1] http://tratt.net/laurie/
[2] http://www.se-radio.net/2007/05/episode-57-compile-time-metaprogrammin…
gabriel · 2013-12-05
I believe he explains this switch here: http://tratt.net/laurie/blog/entries/fast_enough_vms_in_fast_enough_ti…
It's a very good read. IIRC, the reasons aren't really rooted in the language that is used. It's more about the tooling provided by PyPy for constructing a compiler.
masklinn · 2013-02-06
http://tratt.net/laurie/tech_articles/articles/fast_enough_vms_in_fast… is probably the best example, because — as far as I know — outside of having reimplemented his Converge in RPython Laurence Tratt is not affiliated with the pypy project in any way, shape or form.
njs12345 · 2011-12-12
I'm not sure I'd necessarily agree with your assessment of parsing as a field in 2011. There are still a lot of unsolved problems going forward --- see Laurence Tratt's excellent article on the subject for a few details: http://tratt.net/laurie/tech_articles/articles/parsing_the_solved_prob…
feznyng · 2026-01-22
LSPs rely on a parser to generate an AST for a given language. This parser needs to be error-tolerant because it needs to return usable ASTs despite often parsing incomplete, incorrect code and fast enough to run on every keystroke so it can provide realtime feedback.
Most of the time they rely on their own hand-rolled recursive descent parser. Writing these isn't necessarily hard but time-consuming and tedious especially if you're parsing a large language like C++.
Parser generators like yacc, bison, chumsky, ANTLR etc. can generate a parser for you given a grammar. However these parsers usually don't have the best performance or error reporting characteristics because they are auto-generated. A recursive descent parser is usually faster and because you can customize syntax error messages, easier for an LSP to use to provide good diagnostics.
Tree-sitter is also a parser generator but has better error tolerance properties (not quite as good as hand-written but generally better than prior implementations). Additionally, its incremental meaning it can reuse prior parses to more efficiently create a new AST. Most hand-written parsers are not incremental but are usually still fast enough to be usable in LSPs.
To use tree-sitter you define a grammar in JavaScript that tree-sitter will use to generate a parser in C which you can then use a dynamic or static library in your application.
In your case, this is useful because you can compile down those C libraries to WASM which…
Zababa · 2022-06-22
> new books should use more modern popular languages to age well and to attract younger audience
That doesn't make sense. Java is one of the most popular programming language, more popular than a lot of other "modern popular languages". The only languages more popular are either as old as Java (JavaScript, Python) or older (C, C++). C# might be one option, but it's close to Java, and I don't know if the support for Linux/MacOS was here at the time this book was started. Same thing for JavaScript and Python's popularity, which are relatively recent trends. On the other hand, Java has stayed and endured. It's still here and will still probably be here in 20 years.
> on the JVM there are languages better suited for the topic (e.g. Scala by a large margin)
Scala is less popular than Java, and harder to master. Once you consider Scala, you get into endless arguments about whether to use Scala, SML, OCaml, Haskell, etc.
> There's already the "Language Implementation Patterns" book
There is also "Writing an interpreter in Go" and "Writing a compiler in Go" that seem to cover the same ground. But I'm certain than more people know about interpreters and compilers thanks to these three books than thanks to any one of them.
> but also gives you real life skills (e.g. ANTLR is used in most big data query engines)
The majority of programming languages don't use a generated parser but a handmade recursive descent parser, because it's the best at error reporting. There's a good post…
ltratt · 2017-04-11
My gut feeling is that one can minimally maintain systems in "forgotten" languages indefinitely if they're basically stable and feature complete. But it seems that people come unstuck for systems that still need to evolve -- even if that evolution is slow and/or sporadic. The obvious alternative is to rewrite systems in new languages, but that is generally prohibitively expensive. Even for those that can afford the expense, the new system tends to not to take considerable time to bed in, so flipping the switch from the old to the new is only for the brave or those with excellent PR departments.
Although we didn't have this in mind when we started on this work, I've come to think that language composition might offer a way out of this mess (I immodestly offer [1] as an early example). If one composes an old and a new language, one can migrate a system from an old to a new language bit-by-bit. As well as amortising the translation cost, it also means that one can minimise the "switch flipping" problem: disasters seem much less likely if the composed system can be introduced gradually.
[1] http://tratt.net/laurie/blog/entries/fine_grained_language_composition…
juliangamble · 2014-08-21
Robert Harper argues that dynamically typed languages are languages of a single Type:
And this is precisely what is wrong with dynamically typed languages: rather than affording the freedom to ignore types, they instead impose the bondage of restricting attention to a single type! Every single value has to be a value of that type, you have no choice!
http://existentialtype.wordpress.com/2011/03/19/dynamic-languages-are-…
Bob in this same article also wrote the now oft quoted:
To borrow an apt description from Dana Scott, the so-called untyped (that is “dynamically typed”) languages are, in fact, unityped.
Now the author of the linked article wrote another piece in 2012 that rebuts this:
It therefore makes no sense to say that a language is unityped without qualifying whether that relates to its static or dynamic type system. Python, for example, is statically unityped and dynamically multityped; C is statically multityped and dynamically unityped; and Haskell is statically and dynamically multityped. Although it's a somewhat minor point, one can argue (with a little hand waving) that many assembly languages are both statically and dynamically unityped.
http://tratt.net/laurie/blog/entries/another_non_argument_in_type_syst…
It is worth noting:
Sam Tobin-Hochstadt argues the uni-typed classification is not very informative in practice.
The uni-typed theory reveals little about the nature of programming in a dynamically typed language; it's mainly…
kragen · 2011-03-16
PEGs are one class of cleanly composable grammars. OMeta uses that attribute of theirs to great advantage. And PEGs are, formally speaking, parsable in worst-case linear time, although whether that linear time is fast enough to be practical is still unknown, and it also potentially uses large linear space. I hope it's not vulgar to post yet another link to my minimal PEG parser generator in one page of code: https://github.com/kragen/peg-bootstrap/blob/master/peg.md
In particular, the example here of embedding SQL in C would be pretty trivial to do as a PEG.
PEGs can parse some languages that are not context-free — the example from Bryan Ford's thesis is aₓbₓcₓ, where xᵢ means "i repetitions of x". I think there are also context-free languages they can't parse, but I'm not sure.
(Operator precedence parsing is particularly ugly in PEGs, since by default, they don't support left recursion. The OMeta folks figured out how to cleanly support left recursion in PEGs, but you lose the linear-time guarantee.)
One very appealing attribute of PEGs is that you can conveniently extend PEGs to support parameterized productions, which could be crucial in building up a library of general-purpose parsing productions that could reasonably be used to shorten the time to define new languages.
k4st claims in http://news.ycombinator.com/item?id=2330672 that Pratt top-down operator-precedence parsers are also cleanly composable. I didn't know that, and it seems like a surprising claim,…
aw1621107 · 2025-12-10
> Is it something that can be fixed with editions? My guess is no, or at least not easily.
Assuming I'm reading these blog posts [0, 1] correctly, it seems that the size_of::<usize>() == size_of::<*mut u8>() assumption is changeable across editions.
Or at the very least, if that change (or a similarly workable one) isn't possible, both blog posts do a pretty good job of pointedly not saying so.
[0]: https://faultlore.com/blah/fix-rust-pointers/#redefining-usize
[1]: https://tratt.net/laurie/blog/2022/making_rust_a_better_fit_for_cheri_…
GuB-42 · 2025-07-27
If you like these kind of posts, maybe you should go to https://hackaday.com/ it is all articles like this every day, though usually more on the hardware side.
Here is one in the same vein: https://hackaday.com/2023/04/15/internet-of-washing-machines-solves-an… => https://tratt.net/laurie/blog/2023/displaying_my_washing_machines_rema…
dan-robertson · 2024-12-24
Re VM warmup, see https://tratt.net/laurie/blog/2022/more_evidence_for_problems_in_vm_wa… and the linked earlier research for some interesting discussion. Roughly, there is a belief when benchmarking that one can work around not having the most-optimised JIT-compiled version by running your benchmark a number of times and then throwing away the result before doing ‘real’ runs. But it turns out that:
(a) sometimes the jit doesn’t run
(b) sometimes it makes performance worse
(c) sometimes you don’t even get to a steady state with performance
(d) and obviously in the real world you may not end up with the same jitted version that you get in your benchmarks
smartmic · 2024-11-19
A capable alternative based on "boring, old" technology is multitime [1]
Back at the time I needed it, it had peak memory usage - hyperfine was not able to show it. Maybe this had changed by now.
[1] https://tratt.net/laurie/src/multitime/
trealira · 2024-10-16
> The DeathStation 9000 features a conforming C implementation which is known to catch all array bounds violations. ;)
That actually really does exist already with CHERI CPUs, whose pointers are tagged with "capabilities," which catch buffer overruns at runtime.
https://tratt.net/laurie/blog/2023/two_stories_for_what_is_cheri.html
https://msrc.microsoft.com/blog/2022/01/an_armful_of_cheris/
davidkellis · 2024-02-21
These are not new, but my takeaways from https://tratt.net/laurie/blog/2020/which_parsing_approach.html and https://rust-analyzer.github.io/blog/2020/09/16/challeging-LR-parsing.… are to embrace various forms of LR parsing. https://github.com/igordejanovic/parglare is a very capable GLR parser, and I've been keeping a close eye on it for use in my projects.
matheusmoreira · 2024-01-09
I envy these small and steady improvements!!
I spent about one week implementing PyPy's storage strategies in my language's collection types. When I finished the vector type modifications, I benchmarked it and saw the ~10% speed up claimed in the paper¹. The catch is performance increased only for unusually large vectors, like thousands of elements. Small vectors were actually slowed down by about the same amount. For some reason I decided to press on and implement it on my hash table type too which is used everywhere. That slowed the entire interpreter down by nearly 20%. The branch is still sitting there, unmerged.
I can't imagine how difficult it must have been for these guys to write a compiler and succeed at speeding up the Python interpreter.
¹ https://tratt.net/laurie/research/pubs/html/bolz_diekmann_tratt__stora…
akyuu · 2023-11-03
No, AFAIK Morello project is about designing an Arm CPU with CHERI, a hardware architecture with extra security capabilities that is still WIP: https://tratt.net/laurie/blog/2023/two_stories_for_what_is_cheri.html
earthboundkid · 2023-10-09
I read https://tratt.net/laurie/blog/2016/fine_grained_language_composition.h… this week, and now I’m obsessed with how all three of the techniques presented here suck, and we should just be able to mix languages freely.
cyber_kinetist · 2023-09-19
> Doesn’t Rust also provide buffer overrun protection, without needing a special OS or CPU instruction set?
No, because there’s still quite a lot of (inevitable) Unsafe Rust code floating around, and the compiler can’t protect these from memory-related errors. In fact there are some ongoing discussions and progress to support CHERI in Rust:
[0] https://faultlore.com/blah/fix-rust-pointers/
[1] https://tratt.net/laurie/blog/2022/making_rust_a_better_fit_for_cheri_…
[2] https://archive.fosdem.org/2023/schedule/event/rust_a_rusty_cheri_the_…
rwmj · 2023-09-19
This was posted yesterday and has quite a good overview:
https://tratt.net/laurie/blog/2023/two_stories_for_what_is_cheri.html
vchuravy · 2023-09-07
Yeah in the end this the difference between dynamical and static typing.
I enjoy
https://tratt.net/laurie/research/pubs/html/tratt__dynamically_typed_l… as a discussion of dynamic typing.
moonchild · 2023-04-29
Also of interest: 'Why Aren’t More Users More Happy With Our VMs?'—https://tratt.net/laurie/blog/2018/why_arent_more_users_more_happy_wit…
DuncanMak · 2022-12-12
This article seems like a nice overview of the pros and cons of the Icon expression evaluation system:
https://tratt.net/laurie/research/pubs/html/tratt__experiences_with_an…
JustSomeNobody · 2022-08-10
Here's a link to an article where they provide a shell script to easily do it:
https://tratt.net/laurie/blog/2022/making_a_video_of_a_single_window.h…
pkolaczk · 2021-03-04
I was talking about JITs in general. Sure, you can AOT-compile .NET code quite efficiently, but then this is a different story.
Here is a nice analysis of how various JITs warmup in practice:
https://tratt.net/laurie/blog/entries/why_arent_more_users_more_happy_…
TL;DR; often they don't!