Per thread heap, GC, etc.
Markk
markus.kuehni at triviso.ch
Fri May 14 13:48:12 UTC 2021
Hi,
D has this nice default per-thread static memory model, i.e. if I
understand all this correctly, this allows for better, more
natural thread safety, while it makes it generally unsafe to use
this memory from other threads (without locking). I guess the
same is implicitly true for stack memory.
Now could it equally make sense to use per-thread heaps?
I.e. all allocations would need to be per thread, and it would be
illegal to reference memory of one thread's heap, static memory,
or stack from another thread's memory.
Some RAII locking could pin message-passed (etc.) references
temporarily down for them to be used legally by another thread.
This would make the sharing of the pointer known to the original
thread for a strictly scoped time. Perhaps the `synchronized`
keyword could be used for these stack references (just a spur of
the moment proposal for the purpose of this discussion). Pinning
is coupled with message-passing (etc.), i.e. no additional
locking required.
For permanent change of ownership i.e. storing a reference in
static or heap memory of the other thread, the referenced memory
would have to be copied. I.e. there are no `synchronized`
references from inside static or heap (i.e. non-stack,
non-scoped) memory.
I guess `synchronized` class objects could get their own,
non-thread specific, a.k.a. shared heap (similar in a way to the
`shared` static memory). All stack references to `synchronized`
class objects would have to be marked with `synchronized` too (or
this might be inferred). `synchronized` class references stored
in other (non-stack, non-scoped) thread memory would still be
illegal.
Given the above, the GC could be run per thread. The world would
not have to be stopped! Which means that some threads could
entirely run without GC while others could still benefit from
what I personally think is the only universal and scalable
solution to memory safety. As a middle ground, some threads might
only use a controlled amount of allocations, therefore GC runs
would be super-fast, perhaps still acceptable under (near)
real-time performance constrains.
The model would force developers towards a more modularized, per
thread (service?) oriented architecture where message passing and
lock free programming would be king... (said from a "schoolbook"
understanding of these matters ;-)).
Also, I guess the performance of the resulting lock free heap
allocs/frees, of the now (by language guarantee) lock free thread
safe memory accesses, of the now per thread, smaller and (per
definition) lock free GC runs etc. would improve.
Being per-thread i.e. non-preemptive, this could also simplify
the GC and allow for more compiler optimizations, I guess. There
is no danger of register aliasing and whatnot, that I can only
guess makes preemptively interrupting GC correctness under high
compiler optimization hard.
Just some thoughts after reading a handful Rust and D books...
and after having seen so many wrinkle their noses at GC ... and
therefore, unfortunately D.
_Mark
More information about the Digitalmars-d
mailing list