Migrating an existing more modern GC to D's gc.d
David Bennett
davidbennett at bravevision.com
Tue Apr 10 07:55:00 UTC 2018
On Tuesday, 10 April 2018 at 06:47:53 UTC, Jonathan M Davis wrote:
> As it stands, it's impossible to have thread-local memory
> pools. It's quite legal to construct an object as shared or
> thread-local and cast it to the other. In fact, it's _highly_
> likely that that's how any shared object of any complexity is
> going to be constructed. Similarly, it's extremely common to
> allocate an object as mutable and then cast it to immutable
> (either using assumeUnique or by using a pure function where
> the compiler does the cast implicitly for you if it can
> guarantee that the return value is unique), and immutable
> objects are implicitly shared.
>
(Honest question:) Do people really cast from local to
shared/immutable and expect it to work?
(when ever I cast something more complex then a size_t I almost
expect it to blow up... or break sometime in the future)
That said, I can understanding building a shared object from
parts of local data... though I try to keep my thread barriers as
thin as possible myself. (meaning I tend to copy stuff to the
shared and have as few shared's as possible)
>
> At minimum, there would have to be runtime hooks to do
> something like move an object between pools when it is cast to
> shared or immutable (or back) in order to ensure that an object
> was in the right pool, but if that requires copying the object
> rather than just moving the memory block, then it can't be
> done, because every pointer or reference pointing to that
> object would have to be rewritten (which isn't supported by the
> language).
>
A hook for local to cast(shared) could work... but would require
a DIP I guess. I was hoping to make a more incremental
improvement the the GC.
>
> Also, it would be a disaster for shared, because the typical
> way to use shared is to protect the shared object with a mutex,
> cast away shared so that it can be operated on as thread-local
> within that section of code, and then before the mutex is
> released, all thread-local references then need to be gone. e.g.
>
>
> synchronized(mutex)
> {
> auto threadLocal = cast(MyType)mySharedObject;
>
> // do something with threadLocal...
>
> // threadLocal leaves scope and is gone without being cast
> back
> }
>
> // all references to the shared object should now be shared
>
Yeah thats why I was still scanning all thread stacks and pages
when marking global data.
So a shared -> local is a no op but the other way needs thought.
>
> You really _don't_ want the shared object to move between pools
> because of that cast (since it would hurt performance), and in
> such a
> situation, you don't usually cast back to shared. Rather, you
> have a shared
> reference, cast it to get a thread-local reference, and then
> let the
> thread-local reference leave scope. So, the same object
> temporarily has both
> a thread-local and a shared reference to it, and if it were
> moved to the
> thread-local pool with the cast, it would never be moved back
> when the
> thread-local references left scope and the mutex was released.
>
> Having synchronized classes as described in TDPL would make the
> above code cleaner in the cases where a synchronized class
> would work, but the basic concept is the same. It would still
> be doing a cast underneath the hood, and it would still have
> the same problems. It just wouldn't involve explicit casting.
> shared's design inherently requires casting away shared, so it
> just plain isn't going to play well with anything that doesn't
> play well with such casts - such as having thread-local heaps.
>
I would think a shared class would never be marked as a
THREAD_LOCAL as it has a shared member.
>
> Also, IIRC, at one point, Daniel Murphy explained to me some
> problem with classes with regards to the virtual table or the
> TypeInfo that inherently wouldn't work with trying to move it
> between threads. Unfortunately, I don't remember the details
> now, but I do remember that there's _something_ there that
> wouldn't work with thread-local heaps. And if anyone were to
> seriously try it, I expect that he could probably come up with
> the reasons again.
>
> Regardless, I think that it's clear that in order to do
> anything with thread-local pools, we'd have to lock down the
> type system even further to disallow casts to or from shared or
> immutable, and that would really be a big problem given the
> inherent restrictions on those types and how shared is intended
> to be used. So, while it's a common idea as to how the GC could
> be improved, and it would be great if we could do it, I think
> that it goes right along with all of the other ideas that
> require stuff like read and write barriers everywhere and thus
> will never be in D's GC.
>
> - Jonathan M Davis
Yeah I thought it would have issues, thanks for your feedback!
I'll see if I can come up with a better idea that doesn't break
as much stuff.
More information about the Digitalmars-d
mailing list