Garbage Collection
- GC for Systems Programmers - a very effective defense of GC as such, in particular "Lies people believe about memory management"
- an anonymous malloc() rant - not praising GC at all, but if you aren't using composable and explicit custom allocators, which can dodge the complaints expressed here in a way that RAII and Rust don't dodge, then why not just use GC in a more disciplined manner? Because you're not getting as much as you might think from the technology vs. the discipline.
Comparisons
- vs. F#: Why I chose OCaml as my primary language - not focused on the comparison. In F#'s favor: computational expressions, type providers, active patterns, statically resolved type parameters, .NET interop. And against it: lack of a module language, incompatible object model, no local/generalized opens, no polymorphic variants, no GADTs, no user-defined effects, no extensible sumtypes.
- vs. Python: OCaml: what you gain - mostly positive, but notably:
In the SAT solver, I declared the type of a literal abstractly as
type litand, internally, I usedtype lit = int(an array index). That worked fine. Later, I changed the internal representation from an int to a record. Ideally, that would have no effect on users of the module, but OCaml allows testing abstract types for equality, which resulted in each comparison recursively exploring the whole SAT problem. It can also cause runtime crashes if it encounters a function in this traversal. Haskell's type classes avoid this problem by letting you control which types can be compared and how the comparison should be done.
Performance
- https://roscidus.com/blog/blog/2024/07/22/performance/ - very thorough and tool-heavy troubleshooting of a performance degradation on a rewrite from Lwt to Eio. With a followup, in particular:
(The significant improvement from removing an auxiliary loop is kind of appalling.)OCaml has a major heap for long-lived values, plus one fixed-size minor heap for each domain. New allocations are made sequentially on the allocating domain's minor heap (which is very fast, just adjusting a pointer by the size required).
When the minor heap is full the program performs a minor GC, moving any values that are still reachable to the major heap and leaving the minor heap empty.
Garbage collection of the major heap is done in small slices so that the application doesn't pause for long, and domains can do marking and sweeping work without needing to coordinate (except at the very end of a major cycle, when they briefly synchronise to agree a new cycle is starting).
However, as minor GCs move values that other domains may be using, they do require all domains to stop.