Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two issues #2

Open
NIC0NIC0NI opened this issue Nov 24, 2017 · 1 comment
Open

Two issues #2

NIC0NIC0NI opened this issue Nov 24, 2017 · 1 comment

Comments

@NIC0NIC0NI
Copy link

According to mark_n_sweep_gc.txt, these two are the disadvantages of reference counting. But I could not find the solution to them in mark-and-sweep GC.

  1. Noticeable performance penalty. Each manipulation with pointers requires update of counter.
    In case of multithreaded application we have to use atomic operations or synchronization primitives to avoid race conditions.

Atomic operations are only required if one thread allocates an object and passes the reference to another. However, I noticed that the mark-and-sweep MemoryAllocator is thread local, which cannot handle the shared references. If one thread A allocates an object O and passes the reference to another thread B, there are possibility that A does not hold the reference from root to O and deallocate it, while B still holds the reference. In order to handle this, all involed threads must be blocked before GC, and it brings performance penalty. Therefore, high performance GC in multi-thread context is not an easy thing.

  1. Deleting last reference to huge tree of objects can cause large number of cascade (recursive) deletes which can cause stack overflow.

However, in mark-and-sweep collector, marking last reference to huge tree of objects can cause large number of cascade (recursive) marks which can cause stack overflow. This is easy to solve through manual implemented stack.

@knizhnik
Copy link
Owner

I mostly agree with both your arguments. But few comments:

  1. Quite often thread is not updating shared objects. It just create and delete its own private objects. But it can certainly refer global objects (either through local variable, either from fields of it's private objects). In case of reference counters we have to update shared reference counter. and it doesn't work without synchronization/atomic operations. But in case of mark&sweep we can perform local GC without any synchronization.
  2. Yes, object graphs should be carefully traversed to avoid stack overflow. Manually implemented stack is one of the possible solutions, but not the perfect one: we are not limited in this case with OS limit for stack size, but still traverse of large collection in "wrong" order can produce huge stack and cause memory exhaustion. Another alternatives is custom traverse method specific for particular collection and bitmaps. Bitmap allows to eliminate problem with too deep recursion, but traversing bitmap may be much more expensive than manipulations with stack. Bitmaps are mostly used for collecting garbage in persistent storages, because in this case locality of object access is most critical.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants