summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2023-05-18 09:20:56 -0400
committerPeter Zhu <peter@peterzhu.ca>2023-05-25 08:56:22 -0400
commite87f6c899e55f4d9452ce4d75cf2a725ae736aff (patch)
tree77e699cfeb98a97719f97ff465a852163ac905ca /test
parent57fce84c14820df735136351b5198673ed484b71 (diff)
Don't immediately promote children of old objects
[Feature #19678] References from an old object to a write barrier protected young object will not immediately promote the young object. Instead, the young object will age just like any other object, meaning that it has to survive three collections before being promoted to the old generation. References from an old object to a write barrier unprotected object will place the parent object in the remember set for marking during minor collections. This allows the child object to be reclaimed in minor collections at the cost of increased time for minor collections. On one of [Shopify's highest traffic Ruby apps, Storefront Renderer](https://shopify.engineering/how-shopify-reduced-storefront-response-times-rewrite), we saw significant improvements after deploying this feature in production. We compare the GC time and response time of web workers that have the original behaviour (non-experimental group) and this new behaviour (experimental group). We see that with this feature we spend significantly less time in the GC, 0.81x on average, 0.88x on p99, and 0.45x on p99.9. This translates to improvements in average response time (0.96x) and p99 response time (0.92x).
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/7821
Diffstat (limited to 'test')
-rw-r--r--test/ruby/test_gc.rb26
1 files changed, 26 insertions, 0 deletions
diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb
index 3ff2d8bff2..7e160817c8 100644
--- a/test/ruby/test_gc.rb
+++ b/test/ruby/test_gc.rb
@@ -652,4 +652,30 @@ class TestGc < Test::Unit::TestCase
Module.new.class_eval( (["# shareable_constant_value: literal"] +
(0..100000).map {|i| "M#{ i } = {}" }).join("\n"))
end
+
+ def test_old_to_young_reference
+ original_gc_disabled = GC.disable
+
+ require "objspace"
+
+ old_obj = Object.new
+ 4.times { GC.start }
+
+ assert_include ObjectSpace.dump(old_obj), '"old":true'
+
+ young_obj = Object.new
+ old_obj.instance_variable_set(:@test, young_obj)
+
+ # Not immediately promoted to old generation
+ 3.times do
+ assert_not_include ObjectSpace.dump(young_obj), '"old":true'
+ GC.start
+ end
+
+ # Takes 4 GC to promote to old generation
+ GC.start
+ assert_include ObjectSpace.dump(young_obj), '"old":true'
+ ensure
+ GC.enable if !original_gc_disabled
+ end
end