> why do languages like Crystal and D still use Boehm?
Languages use Boehm for exactly one reason: it is easy to shim into an otherwise manual memory system (it was designed for use in C/C++). I mean no respect to its authors, but using Boehm in production is the worst of all worlds: slow allocations (free list allocator), poor cache locality, and not precise (so you can expect memory leaks). If you are going to do a GC language you want: 1) precise 2) bump allocator 3) compacting collector 4) generations. Essentially you want to allocate fast, only touch live objects (most objects die young), compact them for locality, and only process objects each cycle of similar age. There is a huge amount of engineering that goes into a state of the art collector, but those are the basics.
This is all true but is a somewhat Java-flavoured perspective i.e. generations ties you into a moving collector, which ties you into barriers and complicates FFI, which is not always the right tradeoff.
A non-fragmenting allocator goes a long way to alleviating the need for compactions too.