Automatic memory management with short pauses that is simple to implement?
I'm looking for recommendations for an automatic memory management scheme for a programming language. It must be portable, concurrent, and have short pause times. Simpler implementation is more important than good performance. Reference-counting and/or tracing garbage collection are both under consideration (I'm open to other suggestions too). The programmer should not have to think about memory management much, if at all (so, if reference-counting is used, the implementation should also detect reference cycles).
When I look at introductory literature, I see simple schemes with long pause times. When I look at popular programming language implementations, I see schemes that are performant at the cost of a complex implementation. But what I want is a simpler implementation, and I am willing to accept poor performance (except for my concern about pause times). By simpler to implement I mean fewer lines of code; if a library for garbage collection, the LOC in that library counts too. This is all all relative; it is understood that the simplest implementation with short pause times may still be pretty complex, and also in addition I will accept a little implementation complexity in exchange for a lot of performance. The criteria are:
portable, concurrent, short pause times > simple implementation > low memory usage > fast
I'm on the fence about compaction. I do want the user to be able to run programs for a long time without running out of memory. But compaction makes interop more complex. Various contemporary language implementations, such as Golang (Go) and Python have non-compacting GC and I don't hear complaints about people's programs crashing due to memory fragmentation. Is fragmentation only a theoretical issue that doesn't come up in practice -- or, do those implementations do something complicated to avoid fragmentation?
This will be a high-level programming language with a runtime. The runtime will know where pointers are and could do things like box values and store GC metadata there, have write barriers and/or read barriers, reference count, etc.
Why not a vanilla mark-sweep collector? That can have long pause times.
Why not the Boehm-Demers-Weiser conservative garbage collector ( https://www.hboehm.info/gc/ )? (a) it is not portable; the docs say "Our collector is not, and cannot be, implemented as completely portable C code." In concurrent, incremental mode it appears to be even less portable. (b) It has many lines of code. (c) Because our runtime will know where pointers are, we do not need a conservative collector.
What do you recommend? Thanks in advance.