On Tuesday, 15 October 2013 at 11:03:01 UTC, Michel Fortin wrote:
On 2013-10-15 02:20:49 +0000, "deadalnix" <deadal...@gmail.com> said:

It will indeed cause trouble for code that mutate a large amount of shared pointers. I'd say that such code is probably asking for trouble in the first place, but as always, no silver bullet. I still think solution is the one that fit D the best.

I think there's a small mistake in your phrasing, but it makes a difference.

When the collector is running, it needs to know about any mutation for pointers to its shared memory pool, including pointers that are themselves thread-local but point to shared memory. So COW will be trouble for code that mutate a large amount of **pages containing pointers to shared memory**. And this which includes **pointers to immutable data** because immutable is implicitly shared. And this includes **pointers to const data** since those pointers might point to immutable (thus shared) memory.


No, that is the beauty of it :D

Consider you have pointer from Tl -> shared -> immutable and TL -> immutable.

I'm not covering TL collection here (It seem to be obvious that it doesn't require to stop the world). So the starting point is that we have the roots in all TL heaps/stacks, and we want to collect shared/immutable without blocking the worlds.

TL heap may get new pointers to the shared heap, but they can only come from the shared heap itself or new allocations. At this point, you consider every new allocations as live.

Reading a pointer from the shared heap and copy it to the TL heap isn't problematic in itself, but then we have a problem if this pointer is now updated in the shared heap, as the GC may never scan this pointer.

This is why you need to track pointer writes to the shared heap. The write value itself isn't important : it come from either new alloc that are live, or from somewhere else in the shared heap (so it will be scanned as we track writes).

So any memory page susceptible of containing pointers to shared memory would need to use COW during collection. Which means all the thread's stacks, and also all objects with a pointer to shared, immutable, and const data. At this point I think it is fair to approximate this to almost all memory that could contain pointers.

No, only the shared one, that is the beauty of the technique. Not that I'm not making that up myself, it is how GC used to work in the Caml family for a while, and it has proven itself really efficient (in Caml family, most data are either immutable or thread local, and the shared heap typically small).

Reply via email to