Thread GC non "stop-the-world"
Rikki Cattermole via Digitalmars-d
digitalmars-d at puremagic.com
Mon Sep 22 18:58:48 PDT 2014
On Tuesday, 23 September 2014 at 00:15:51 UTC, Oscar Martin wrote:
> The cost of using the current GC in D, although beneficial for
> many types of programs, is unaffordable for programs such as
> games, etc... that need to perform repetitive tasks every short
> periods of time. The fact that a GC.malloc/realloc on any
> thread can trigger a memory collection that stop ALL threads of
> the program for a variable time prevents it. Conversations in
> the forum as "RFC: reference Counted Throwable", "Escaping the
> Tyranny of the GC: std.rcstring, first blood" and the @nogc
> attribute show that this is increasingly perceived as a problem.
> Besides the ever-recurring "reference counting", many people
> propose to improve the current implementation of GC. Rainer
> Schuetze developed a concurrent GC in Windows:
>
> http://rainers.github.io/visuald/druntime/concurrentgc.html
>
> With some/a lot of work and a little help compiler (currently
> it indicates by a flag if a class/structure contains
> pointers/references to other classes/structures, it could
> increase this support to indicate which fields are
> pointers/references) we could implement a
> semi-incremental-generational-copying GC-conservative like:
>
> http://www.hboehm.info/gc/
> or
> http://www.ravenbrook.com/project/mps/
>
> Being incremental, they try to minimize the "stop-the-world"
> phase. But even with an advanced GC, as programs become more
> complex and use more memory, pause time also increases. See for
> example (I know it's not normal case, but in a few years ...)
>
>
> http://blog.mgm-tp.com/2014/04/controlling-gc-pauses-with-g1-collector
>
> (*) What if:
> - It is forbidden for "__gshared" have references/pointers to
> objects allocated by the GC (if the compiler can help with this
> prohibition, perfect, if not the developer have to know what he
> is doing)
> - "shared" types are not allocated by the GC (they could be
> reference counted or manually released or ...)
> - "immutable" types are no longer implicitly "shared"
>
> In short, the memory accessible from multiple threads is not
> managed by the GC.
>
> With these restrictions each thread would have its
> "I_Allocator", whose default implementation would be an
> incremental-generational-semi-conservative-copying GC, with no
> inteference with any of the other program threads (it should be
> responsible only for the memory reserved for that thread).
> Other implementations of "I_Allocator" could be based on
> Andrei's allocators. With "setThreadAllocator" (similar to
> current gc_setProxy) you could switch between the different
> implementations if you need. Threads with critical time
> requirements could work with an implementation of "I_Allocator"
> not based on the GC. It would be possible simulate scoped
> classes:
>
> {
> setThreadAllocator(I_Allocator_pseudo_stack)
> scope(exit) {
> I_Allocator_pseudo_stack.deleteAll();
> setThreadAllocator(I_Allocator_gc);
> }
> auto obj = MyClass();
> ...
> // Destructor are called and memory released
> }
>
> Obviously changes (*) break compatibility with existing code,
> and therefore maybe they are not appropriate for D2. Also these
> are general ideas, sure these changes lead to other problems.
> But the point I want to convey is that in my opinion, while
> these problems are solvable, a language for "system
> programming" is incompatible with shared data managed by a GC
>
> Thoughts?
Short, I dislike pretty much all changes to __gshared/shared.
Breaks too many things.
Atleast with Cmsed, (I'm evil here) where I use __gshared
essentially as a read only variable but modifiable when starting
up (to modify need synchronized, to read doesn't).
I have already suggested before in threads something similar to
what your suggesting with regards to setting allocator except:
The memory manager is in a stack. Default is GC e.g. the current
one.
Compiler knows which pointers escapes. Can pass to pure functions
however.
with(myAllocator) { // myAllocator.opWithIn
...//allocate
} // myAllocator.opWithCanFree
// myAllocator.opWithOut
class MyAllocator : Allocator {
override void opWithIn(string func = __FUNCTION__, int line =
__LINE__) {
GC.pushAllocator(this);
}
override void opWithCanFree(void** freeablePointers) {
//...
}
override void opWithOut(string func = __FUNCTION__, int line =
__LINE__) {
GC.popAllocator();
}
void* alloc(size_t amount) {
return ...;
}
void free(void*) {
//...
}
}
You may have something about thread allocators though. Humm
druntime would already need changes so maybe.
Ehh this really needs a DIP instead of me whining. If I do it,
ETA December.
More information about the Digitalmars-d
mailing list