Project

General

Profile

Feature #16984

Remove write barrier exemption for T_ICLASS

Added by alanwu (Alan Wu) 3 months ago. Updated about 1 month ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:98935]

Description

Currently, iclasses are "shady", or not protected by write
barriers. Because of that, the GC needs to spend more time marking these
objects than otherwise. Let's insert write barriers for iclasses.

Applications that use modules heavily should see reduction in GC
time as they have a significant number of live iclasses on the heap.

  • Put logic for iclass method table ownership into a function
  • Remove calls to WB_UNPROTECT and insert write barriers for iclasses

The change relies on the following invariant: for any non origin iclass I,
RCLASS_M_TBL(I) == RCLASS_M_TBL(RBasic(I)->klass). This invariant
did not hold prior to 98286e9 for classes and modules that have prepended
modules.


Patch: https://github.com/ruby/ruby/pull/3410

This is the second version of this change. It's much simpler and it
doesn't introduce new garbage collected objects. I realized that despite
saving a pointer to some other object's method table, iclasses don't
mark the method tables. So, for each method table, there is an unique
object that's responsible for marking it. Since write barriers are only
needed for the object that is marking the newly written value (correct me
if I'm wrong here), having an unique object that marks the tables
makes things straight forward.

The numbers from v1 of this patch was a bit inflated because we were
allocating an excessive amount of iclasses.
I measured again and an app that has an approximately 250MiB heap
saw a 22% reduction in minor GC time.

Credits to tenderlovemaking (Aaron Patterson) for motivating this change.

Updated by ko1 (Koichi Sasada) 3 months ago

Thank you for great work. This kind of hack can cause BUGs easily.

Private app A's heap size is about 22 MiB compared to B's 250 MiB.

Could you measure the memory/objects consumption before and after this patch if it is not difficult?
Maybe no problem, but I want to confirm.

Updated by alanwu (Alan Wu) 3 months ago

Could you measure the memory/objects consumption before and after this patch if it is not difficult?

I took measurements on app B. It's a large Rails app with lots of classes and modules.
The amount of retained memory is not deterministic unfortunately, so I can only give a rough summary.

Change to median Change to average
GC::Profiler "Total Size" 7 MiB 1 MiB
VmRSS from the /proc 4 MiB -5 MiB

The increase to GC heap size makes sense, I expect about 5 MiB more objects given the number of
classes and modules in the app. There is not much change to RSS I guess because the
patch moves what used to be on the malloc heap to the GC heap.

Updated by alanwu (Alan Wu) 2 months ago

  • Description updated (diff)

Edit: I noticed that T_ICLASS wasn't marking the shared method and constant table on master. My notes
about reducing the number of gc_mark references on the heap were incorrect.

Updated by ko1 (Koichi Sasada) about 2 months ago

sorry I didn't check it.

Thank you, ~10 MB in "B's 250 MiB." is not problem I think.
Could you merge it if you don't have any trouble more?

#5

Updated by alanwu (Alan Wu) about 1 month ago

  • Description updated (diff)
  • Subject changed from Remove write barrier examption for T_ICLASS to Remove write barrier exemption for T_ICLASS
#6

Updated by alanwu (Alan Wu) about 1 month ago

  • Description updated (diff)
#7

Updated by alanwu (Alan Wu) about 1 month ago

  • Description updated (diff)
#8

Updated by alanwu (Alan Wu) about 1 month ago

  • Description updated (diff)
#9

Updated by alanwu (Alan Wu) about 1 month ago

  • Status changed from Open to Closed

Applied in changeset git|264e4cd04fbcdcb739a1ff9a84e19afe66005cb2.


Remove write barrier exemption for T_ICLASS

Before this commit, iclasses were "shady", or not protected by write
barriers. Because of that, the GC needs to spend more time marking these
objects than otherwise.

Applications that make heavy use of modules should see reduction in GC
time as they have a significant number of live iclasses on the heap.

  • Put logic for iclass method table ownership into a function
  • Remove calls to WB_UNPROTECT and insert write barriers for iclasses

This commit relies on the following invariant: for any non oirigin
iclass I, RCLASS_M_TBL(I) == RCLASS_M_TBL(RBasic(I)->klass). This
invariant did not hold prior to 98286e9 for classes and modules that
have prepended modules.

[Feature #16984]

Also available in: Atom PDF