Issue #7472 has been reported by sam.saffron (Sam Saffron). ---------------------------------------- Feature #7472: Add a mechanism to remove objects from the GC cycle https://bugs.ruby-lang.org/issues/7472 Author: sam.saffron (Sam Saffron) Status: Open Priority: Normal Assignee: Category: Target version: 2.0.0 For typical rails apps there is a huge largely static object graph in memory. Requests come in, some objects are added, and the GC runs. The blocking nature of the GC introduces a jitter that stops all execution. In our typicalish Rails application, we see approximately 500k objects in the object space, each request add about 150k objects. On our production machine this means the GC stops execution for 30-40ms on a fairly beefy box: GC Profiler ran during this request, if it fired you will see the cost below: GC 457 invokes. Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms) 1 11.169 13134480 17014400 425360 40.00200000000120326149 2 11.249 13350000 17014400 425360 32.00199999999853162080 It is clear that introducing a full scoped generational GC is a massive undertaking, but I was thinking that certain GC apis can make application servers like thin,unicorn or puma operate way more efficiently. How about we add. GC.skip(object) # remove object from GC cycle, essentially copy the ref to a place that is not scanned GC.queue(object) # add an object back to the GC cycle GC.skipped # list all the objects that are skipped Careful use of these methods can reduce GC code by a very large amount as it would reduce fragmentation and logic required to determine if an object is alive or not. Application servers could keep snapshots of object ids on regular intervals and decide which ones to skip. Sure memory usage would rise, but GC blocking would decrease. Thoughts?
on 2012-11-30 00:49
on 2012-11-30 02:05
Issue #7472 has been updated by drbrain (Eric Hodel). sam.saffron (Sam Saffron) wrote: > How about we add. > > GC.skip(object) # remove object from GC cycle, essentially copy the ref to a place that is not scanned What do you mean by "copy"? If you mean "move to a different memory address" this will cause crashes. If a C extension has a reference to the object and you move it you will crash when using the old reference. If the object is referenced on the stack and you dereference the old location you will crash. ---------------------------------------- Feature #7472: Add a mechanism to remove objects from the GC cycle https://bugs.ruby-lang.org/issues/7472#change-34167 Author: sam.saffron (Sam Saffron) Status: Open Priority: Normal Assignee: Category: Target version: 2.0.0 For typical rails apps there is a huge largely static object graph in memory. Requests come in, some objects are added, and the GC runs. The blocking nature of the GC introduces a jitter that stops all execution. In our typicalish Rails application, we see approximately 500k objects in the object space, each request add about 150k objects. On our production machine this means the GC stops execution for 30-40ms on a fairly beefy box: GC Profiler ran during this request, if it fired you will see the cost below: GC 457 invokes. Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms) 1 11.169 13134480 17014400 425360 40.00200000000120326149 2 11.249 13350000 17014400 425360 32.00199999999853162080 It is clear that introducing a full scoped generational GC is a massive undertaking, but I was thinking that certain GC apis can make application servers like thin,unicorn or puma operate way more efficiently. How about we add. GC.skip(object) # remove object from GC cycle, essentially copy the ref to a place that is not scanned GC.queue(object) # add an object back to the GC cycle GC.skipped # list all the objects that are skipped Careful use of these methods can reduce GC code by a very large amount as it would reduce fragmentation and logic required to determine if an object is alive or not. Application servers could keep snapshots of object ids on regular intervals and decide which ones to skip. Sure memory usage would rise, but GC blocking would decrease. Thoughts?
on 2012-11-30 03:03
Issue #7472 has been updated by sam.saffron (Sam Saffron). > if you mean "move to a different memory address" this will cause crashes. no, not at all, leave it exactly where it is, just have objectspace partitioned in 2. the refs that are "skipped" don't get scanned in the lazy sweep. ---------------------------------------- Feature #7472: Add a mechanism to remove objects from the GC cycle https://bugs.ruby-lang.org/issues/7472#change-34174 Author: sam.saffron (Sam Saffron) Status: Open Priority: Normal Assignee: Category: Target version: 2.0.0 For typical rails apps there is a huge largely static object graph in memory. Requests come in, some objects are added, and the GC runs. The blocking nature of the GC introduces a jitter that stops all execution. In our typicalish Rails application, we see approximately 500k objects in the object space, each request add about 150k objects. On our production machine this means the GC stops execution for 30-40ms on a fairly beefy box: GC Profiler ran during this request, if it fired you will see the cost below: GC 457 invokes. Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms) 1 11.169 13134480 17014400 425360 40.00200000000120326149 2 11.249 13350000 17014400 425360 32.00199999999853162080 It is clear that introducing a full scoped generational GC is a massive undertaking, but I was thinking that certain GC apis can make application servers like thin,unicorn or puma operate way more efficiently. How about we add. GC.skip(object) # remove object from GC cycle, essentially copy the ref to a place that is not scanned GC.queue(object) # add an object back to the GC cycle GC.skipped # list all the objects that are skipped Careful use of these methods can reduce GC code by a very large amount as it would reduce fragmentation and logic required to determine if an object is alive or not. Application servers could keep snapshots of object ids on regular intervals and decide which ones to skip. Sure memory usage would rise, but GC blocking would decrease. Thoughts?
on 2012-11-30 03:49
Issue #7472 has been updated by charliesome (Charlie Somerville). What happens if an object in the 'permanent' objectspace references an object in the ephemeral object space? Now this essentially becomes a generational GC and brings along all the implementation problems of one. ---------------------------------------- Feature #7472: Add a mechanism to remove objects from the GC cycle https://bugs.ruby-lang.org/issues/7472#change-34182 Author: sam.saffron (Sam Saffron) Status: Open Priority: Normal Assignee: Category: Target version: 2.0.0 For typical rails apps there is a huge largely static object graph in memory. Requests come in, some objects are added, and the GC runs. The blocking nature of the GC introduces a jitter that stops all execution. In our typicalish Rails application, we see approximately 500k objects in the object space, each request add about 150k objects. On our production machine this means the GC stops execution for 30-40ms on a fairly beefy box: GC Profiler ran during this request, if it fired you will see the cost below: GC 457 invokes. Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms) 1 11.169 13134480 17014400 425360 40.00200000000120326149 2 11.249 13350000 17014400 425360 32.00199999999853162080 It is clear that introducing a full scoped generational GC is a massive undertaking, but I was thinking that certain GC apis can make application servers like thin,unicorn or puma operate way more efficiently. How about we add. GC.skip(object) # remove object from GC cycle, essentially copy the ref to a place that is not scanned GC.queue(object) # add an object back to the GC cycle GC.skipped # list all the objects that are skipped Careful use of these methods can reduce GC code by a very large amount as it would reduce fragmentation and logic required to determine if an object is alive or not. Application servers could keep snapshots of object ids on regular intervals and decide which ones to skip. Sure memory usage would rise, but GC blocking would decrease. Thoughts?
on 2012-11-30 04:27
Issue #7472 has been updated by sam.saffron (Sam Saffron). @charlie looking at the code and the heap design I think there is very little cheating we could do here. I vote to close for now. Perhaps some mechanism for optimising the freelist could give the GC a boost: Something like reorder freelist so it groups on heaps ordered by emptiest heap first, then the lazy sweep can sweep the heaps in allocation order. If you allow for a large amount of free space odds are that your lazy sweep could be really fast. The vast majority of stuff allocated is very short lived. Anyway, any work here is going to require a huge amount of experimentation, the simple api I proposed is not going to be technically feasible, especially since RVALUEs can not be moved and the implications of object references causing leaks (making A permanent could mean you are making B,C,D,E permanent as a side effect) . ---------------------------------------- Feature #7472: Add a mechanism to remove objects from the GC cycle https://bugs.ruby-lang.org/issues/7472#change-34187 Author: sam.saffron (Sam Saffron) Status: Open Priority: Normal Assignee: Category: Target version: 2.0.0 For typical rails apps there is a huge largely static object graph in memory. Requests come in, some objects are added, and the GC runs. The blocking nature of the GC introduces a jitter that stops all execution. In our typicalish Rails application, we see approximately 500k objects in the object space, each request add about 150k objects. On our production machine this means the GC stops execution for 30-40ms on a fairly beefy box: GC Profiler ran during this request, if it fired you will see the cost below: GC 457 invokes. Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms) 1 11.169 13134480 17014400 425360 40.00200000000120326149 2 11.249 13350000 17014400 425360 32.00199999999853162080 It is clear that introducing a full scoped generational GC is a massive undertaking, but I was thinking that certain GC apis can make application servers like thin,unicorn or puma operate way more efficiently. How about we add. GC.skip(object) # remove object from GC cycle, essentially copy the ref to a place that is not scanned GC.queue(object) # add an object back to the GC cycle GC.skipped # list all the objects that are skipped Careful use of these methods can reduce GC code by a very large amount as it would reduce fragmentation and logic required to determine if an object is alive or not. Application servers could keep snapshots of object ids on regular intervals and decide which ones to skip. Sure memory usage would rise, but GC blocking would decrease. Thoughts?
on 2012-12-05 17:04
Issue #7472 has been updated by mame (Yusuke Endoh). Status changed from Open to Rejected ---------------------------------------- Feature #7472: Add a mechanism to remove objects from the GC cycle https://bugs.ruby-lang.org/issues/7472#change-34425 Author: sam.saffron (Sam Saffron) Status: Rejected Priority: Normal Assignee: Category: Target version: 2.0.0 For typical rails apps there is a huge largely static object graph in memory. Requests come in, some objects are added, and the GC runs. The blocking nature of the GC introduces a jitter that stops all execution. In our typicalish Rails application, we see approximately 500k objects in the object space, each request add about 150k objects. On our production machine this means the GC stops execution for 30-40ms on a fairly beefy box: GC Profiler ran during this request, if it fired you will see the cost below: GC 457 invokes. Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms) 1 11.169 13134480 17014400 425360 40.00200000000120326149 2 11.249 13350000 17014400 425360 32.00199999999853162080 It is clear that introducing a full scoped generational GC is a massive undertaking, but I was thinking that certain GC apis can make application servers like thin,unicorn or puma operate way more efficiently. How about we add. GC.skip(object) # remove object from GC cycle, essentially copy the ref to a place that is not scanned GC.queue(object) # add an object back to the GC cycle GC.skipped # list all the objects that are skipped Careful use of these methods can reduce GC code by a very large amount as it would reduce fragmentation and logic required to determine if an object is alive or not. Application servers could keep snapshots of object ids on regular intervals and decide which ones to skip. Sure memory usage would rise, but GC blocking would decrease. Thoughts?
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.