summaryrefslogtreecommitdiff
path: root/test/ruby/test_gc_compact.rb
AgeCommit message (Collapse)Author
2024-10-11Rename supports_auto_compact? to supports_compact?Peter Zhu
It's testing whether GC compaction is supported in general. Notes: Merged: https://github.com/ruby/ruby/pull/11885
2024-10-11Used respond_to? check for compaction in test_gc_compact.rbPeter Zhu
Notes: Merged: https://github.com/ruby/ruby/pull/11885
2024-10-03Rename size_pool -> heapMatt Valentine-House
Now that we've inlined the eden_heap into the size_pool, we should rename the size_pool to heap. So that Ruby contains multiple heaps, with different sized objects. The term heap as a collection of memory pages is more in memory management nomenclature, whereas size_pool was a name chosen out of necessity during the development of the Variable Width Allocation features of Ruby. The concept of size pools was introduced in order to facilitate different sized objects (other than the default 40 bytes). They wrapped the eden heap and the tomb heap, and some related state, and provided a reasonably simple way of duplicating all related concerns, to provide multiple pools that all shared the same structure but held different objects. Since then various changes have happend in Ruby's memory layout: * The concept of tomb heaps has been replaced by a global free pages list, with each page having it's slot size reconfigured at the point when it is resurrected * the eden heap has been inlined into the size pool itself, so that now the size pool directly controls the free_pages list, the sweeping page, the compaction cursor and the other state that was previously being managed by the eden heap. Now that there is no need for a heap wrapper, we should refer to the collection of pages containing Ruby objects as a heap again rather than a size pool Notes: Merged: https://github.com/ruby/ruby/pull/11771
2024-06-07Don't use SEGV signal when timeout in test_gc_compactPeter Zhu
Using a SEGV signal for timeout makes it difficult to tell if it's a real SEGV or if it timed out, so we should just use the default signals.
2024-06-07Extend timeout of TestGCCompect#test_moving_objects_between_size_poolsYusuke Endoh
It is too flaky on macOS GitHub Actions
2024-03-14Ensure test suite is compatible with --frozen-string-literalJean Boussier
As preparation for https://bugs.ruby-lang.org/issues/20205 making sure the test suite is compatible with frozen string literals is making things easier.
2024-02-20Remove never used methodNobuyoshi Nakada
2024-02-20Remove no longer used methodsNobuyoshi Nakada
`find_object_in_recycled_slot` and `memory_location` have not been used since commit:b99833baec2e567e38758f4fd017c90c7ce57d75.
2023-12-09Add a fudge factor to the GC compaction move up/down testsKJ Tsanaktsidis
There seems to be another manifestation of bug #20021, where some of the compaction tests are failing on i686 for unrelated PR's because of fake "live" references to moved objects on the machine stack. We _could_ solve this by counting how many objects are pinned during compaction, but doing that involves pushing down the mark & pin bitset merge into gc_compact_plane and out of gc_compact_page, which I thought was pretty ugly. Now that we've solved bug #20022 though, we're able to compact arbitrarily many objects with GC.verify_compaction_references, so the number of objects we're moving is now 50,000 instead of 500. Since that's now much larger than the number of objects likely to be pinned, I think it's safe enough to just add a fudge-factor to the tests. Any _other_ change in GC.verify_compaction_references that breaks compaction is now highly likely to break the assertion by more than 10 objects, since it's operating on so many more in the first place. [Bug #20021]
2023-12-07Fix GC.verify_compaction_references not moving every objectKJ Tsanaktsidis
The intention of GC.verify_compaction_references is, I believe, to force every single movable object to be moved, so that it's possible to debug native extensions which not correctly updating their references to objects they mark as movable. To do this, it doubles the number of allocated pages for each size pool, and sorts the heap pages so that the free ones are swept first; thus, every object in an old page should be moved into a free slot in one of the new pages. This worked fine until movement of objects _between_ size pools during compaction was implemented. That causes some problems for verify_compaction_references: * We were doubling the number of pages in each size pool, but actually if some objects need to move into a _different_ pool, there's no guarantee that they'll be enough room in that one. * It's possible for the sweep & compact cursors to meet in one size pool before all the objects that want to move into that size pool from another are processed by the compaction. You can see these problems by changing some of the movement tests in test_gc_compact.rb to try and move e.g. 50,000 objects instead of 500; the test is not able to actually move all of the objects in a single compaction run. To fix this, we do two things in verify_compaction_references: * Firstly, we add enough pages to every size pool to make them the same size. This ensures that their compact cursors will all have space to move during compaction (even if that means empty pages are pointlessly compacted) * Then, we examine every object and determine where it _wants_ to be compacted into. We use this information to add additional pages to each size pool to handle all objects which should live there. With these two changes, we can move arbitrary amounts of objects into the correct size pool in a single call to verify_compaction_references. My _motivation_ for performing this work was to try and fix some test stability issues in test_gc_compact.rb. I now no longer think that we actually see this particular bug in rubyci.org, but I also think verify_compaction_references should do what it says on the tin, so it's worth keeping. [Bug #20022]
2023-11-27Fix flaky "Expected 499 to be >= 500" assertion in test_gc_compact.rbKJ Tsanaktsidis
There have been some sproradically flaky tests related to GC compaction, which fail with: 1) Failure: TestGCCompact#test_moving_hashes_down_size_pools [/test/ruby/test_gc_compact.rb:442]: Expected 499 to be >= 500. What's happening here, is that, _sometimes_, depending on very unlucky combinations of machine things, one of the expected-to-be-moved hashes might be found on the machine stack during GC, and thus pinned. One factor which seems to make this _more_ likely is that GCC 11 on Ubuntu 22.04 seems to want to allocate 440 bytes of stack space for `gc_start`, which is much more than it actually uses on the common code path. The result is that there are some 50-odd VALUE-sized cells "live" on the stack which may well contain valid heap pointers from previous function calls, and will need to be pinned. This is, of course, totally normal and expected; Ruby's GC is conservative and if there is the possibility that a VALUE might be live on the machine stack, it can't be moved. However, it does make these tests flaky. This commit "fixes" the tests by performing the work in a fiber; the fiber goes out of scope and should be collected by the call to verify_compaction_references, so there should be no references to the to-be-moved objects floating around on the machine stack. Fixes [#20021]
2023-08-04Revert "Tests to move between size pools are flaky on Windows too"Peter Zhu
This reverts commit c5abe0d08f8f7686422e6eef374cf8c78aefacb6. Notes: Merged: https://github.com/ruby/ruby/pull/8166
2023-08-02Tests to move between size pools are flaky on Windows too [ci skip]Nobuyoshi Nakada
Needs more investigations.
2023-07-31Skip flaky test on SolarisPeter Zhu
This test is flaky on "SPARC Solaris 10 (gcc)" CI with this message: TestGCCompact#test_moving_objects_between_size_pools [test/ruby/test_gc_compact.rb:378]: Expected 499 to be >= 500.
2023-07-31Assert that at least one element has been embeddedPeter Zhu
It's not guaranteed that the first element will always be embedded. Notes: Merged: https://github.com/ruby/ruby/pull/8116
2023-06-23Skip test on Solaris SPARCPeter Zhu
This test fails on Solaris SPARC with the following error and I can't figure out why: TestGCCompact#test_moving_hashes_down_size_pools Expected 499 to be >= 500.
2023-06-06Revert debugging code in test_gc_compact.rbPeter Zhu
2023-05-31More debug code to GC compaction testPeter Zhu
2023-05-31Add debug code to GC compaction testPeter Zhu
This test is flaky on some CI systems.
2023-05-17Move ar_hint to ar_table_structPeter Zhu
This allows Hashes with ST tables to fit int he 80 byte size pool. Notes: Merged: https://github.com/ruby/ruby/pull/7742
2023-05-17Implement Hash AR tables on VWAPeter Zhu
Notes: Merged: https://github.com/ruby/ruby/pull/7742
2023-03-18Fix frozen status loss when moving objectsPeter Zhu
[Bug #19536] When objects are moved between size pools, their frozen status is lost in the shape. This will cause the frozen check to be bypassed when there is an inline cache. For example, the following script should raise a FrozenError, but doesn't on Ruby 3.2 and master. class A def add_ivars @a = @b = @c = @d = 1 end def set_a @a = 10 end end a = A.new a.add_ivars a.freeze b = A.new b.add_ivars b.set_a # Set the inline cache in set_a GC.verify_compaction_references(expand_heap: true, toward: :empty) a.set_a Notes: Merged: https://github.com/ruby/ruby/pull/7553
2023-01-09Assert that resizing arrays will re-embed themPeter Zhu
Notes: Merged: https://github.com/ruby/ruby/pull/7071
2023-01-09Assert that resizing objects will re-embed themPeter Zhu
Notes: Merged: https://github.com/ruby/ruby/pull/7071
2023-01-09Fix re-embedding of strings during compactionPeter Zhu
The reference updating code for strings is not re-embedding strings because the code is incorrectly wrapped inside of a `if (STR_SHARED_P(obj))` clause. Shared strings can't be re-embedded so this ends up being a no-op. This means that strings can be moved to a large size pool during compaction, but won't be re-embedded, which would waste the space. Notes: Merged: https://github.com/ruby/ruby/pull/7071
2023-01-03Fix Error in GC Compaction specsMatt Valentine-House
Previously if any of the tests that move objects between size pools failed to move anything, then the call to stats.dig would return `nil` which would then cause assert_operator to error. This should be a test Failure, rather than an Error so this commit uses a default value of 0 if stats.dig fails to find a key. Also refactor object movement tests to use stats.dig, rather than :[] Notes: Merged: https://github.com/ruby/ruby/pull/6978
2022-12-23Add tests for compacting shared arraysPeter Zhu
Notes: Merged: https://github.com/ruby/ruby/pull/7013
2022-12-23Don't allow re-embedding frozen arraysPeter Zhu
Frozen arrays should not move from heap allocated to embedded because frozen arrays could be shared roots for other (shared) arrays. If the frozen array moves from heap allocated to embedded it would cause issues since the shared array would no longer know where to set the pointer in the shared root. Notes: Merged: https://github.com/ruby/ruby/pull/7013
2022-12-15Fix Object Movement allocation in GCMatt Valentine-House
When moving Objects between size pools we have to assign a new shape. This happened during updating references - we tried to create a new shape tree that mirrored the existing tree, but based on the root shape of the new size pool. This causes allocations to happen if the new tree doesn't already exist, potentially triggering a GC, during GC. This commit changes object movement to look for a pre-existing new tree during object movement, and if that tree does not exist, we don't move the object to the new pool. This allows us to remove the shape allocation from update references. Co-Authored-By: Peter Zhu <peter@peterzhu.ca> Notes: Merged: https://github.com/ruby/ruby/pull/6938
2022-12-15Revert "Fix Object Movement allocation in GC"Peter Zhu
This reverts commit 9c54466e299aa91af225bc2d92a3d7755730948f. We're seeing crashes in Shopify CI after this commit.
2022-12-15Fix Object Movement allocation in GCMatt Valentine-House
When moving Objects between size pools we have to assign a new shape. This happened during updating references - we tried to create a new shape tree that mirrored the existing tree, but based on the root shape of the new size pool. This causes allocations to happen if the new tree doesn't already exist, potentially triggering a GC, during GC. This commit changes object movement to look for a pre-existing new tree during object movement, and if that tree does not exist, we don't move the object to the new pool. This allows us to remove the shape allocation from update references. Co-Authored-By: Peter Zhu <peter@peterzhu.ca> Notes: Merged: https://github.com/ruby/ruby/pull/6926
2022-11-10Transition shape when object's capacity changesJemma Issroff
This commit adds a `capacity` field to shapes, and adds shape transitions whenever an object's capacity changes. Objects which are allocated out of a bigger size pool will also make a transition from the root shape to the shape with the correct capacity for their size pool when they are allocated. This commit will allow us to remove numiv from objects completely, and will also mean we can guarantee that if two objects share shapes, their IVs are in the same positions (an embedded and extended object cannot share shapes). This will enable us to implement ivar sets in YJIT using object shapes. Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/6699
2022-07-15Implement Objects on VWAPeter Zhu
This commit implements Objects on Variable Width Allocation. This allows Objects with more ivars to be embedded (i.e. contents directly follow the object header) which improves performance through better cache locality. Notes: Merged: https://github.com/ruby/ruby/pull/6117
2022-07-12[Feature #18901] Don't run size pool move tests without VWAMatt Valentine-House
Notes: Merged: https://github.com/ruby/ruby/pull/6099
2022-07-12[Feature #18901] Support size pool movement for ArraysMatt Valentine-House
This commit enables Arrays to move between size pools during compaction. This can occur if the array is mutated such that it would fit in a different size pool when embedded. The move is carried out in two stages: 1. The RVALUE is moved to a destination heap during object movement phase of compaction 2. The array data is re-embedded and the original buffer free'd if required. This happens during the update references step Notes: Merged: https://github.com/ruby/ruby/pull/6099
2022-07-11Replace use of double_heap in tests with expand_heapMatt Valentine-House
Notes: Merged: https://github.com/ruby/ruby/pull/6107
2022-06-29Refactor tests for moving strings with compactionPeter Zhu
Notes: Merged: https://github.com/ruby/ruby/pull/6077
2022-06-13Move String RVALUES between poolsMatt Valentine-House
And re-embed any strings that can now fit inside the slot they've been moved to Notes: Merged: https://github.com/ruby/ruby/pull/5986
2022-06-02Move `GC.verify_compaction_references` [Bug #18779]Nobuyoshi Nakada
Define `GC.verify_compaction_references` as a built-in ruby method, according to GC compaction support via `GC::OPTS`. Notes: Merged: https://github.com/ruby/ruby/pull/5972
2022-05-30Fix use-after-free with interacting TracePointsAlan Wu
`vm_trace_hook()` runs global hooks before running local hooks. Previously, we read the local hook list before running the global hooks which led to use-after-free when a global hook frees the local hook list. A global hook can do this by disabling a local TracePoint, for example. Delay local hook list loading until after running the global hooks. Issue discovered by Jeremy Evans in GH-5862. [Bug #18730] Notes: Merged: https://github.com/ruby/ruby/pull/5865
2022-05-24Define unsupported GC compaction methods as rb_f_notimplementMike Dalessio
Fixes [Bug #18779] Define the following methods as `rb_f_notimplement` on unsupported platforms: - GC.compact - GC.auto_compact - GC.auto_compact= - GC.latest_compact_info - GC.verify_compaction_references This change allows users to call `GC.respond_to?(:compact)` to properly test for compaction support. Previously, it was necessary to invoke `GC.compact` or `GC.verify_compaction_references` and check if those methods raised `NotImplementedError` to determine if compaction was supported. This follows the precedent set for other platform-specific methods. For example, in `process.c` for methods such as `Process.fork`, `Process.setpgid`, and `Process.getpriority`. Notes: Merged: https://github.com/ruby/ruby/pull/5934
2022-01-24[wasm] Disallow compactionPeter Zhu
WebAssembly doesn't support signals so we can't use read barriers so we can't use compaction. Notes: Merged: https://github.com/ruby/ruby/pull/5475
2022-01-04Use omit instead of skip: test/ruby/**/*.rbHiroshi SHIBATA
2021-12-17Send the message for s390x to stderr [ci skip]Nobuyoshi Nakada
Parallel worker's stdout is captured as the control protocol. Notes: Merged: https://github.com/ruby/ruby/pull/5286
2021-11-04test/ruby/test_gc_compact.rb: Backpatch the URL to the PRYusuke Endoh
Notes: Merged: https://github.com/ruby/ruby/pull/5077
2021-11-04test/ruby/test_gc_compact.rb: Do not run on s390xYusuke Endoh
The compaction tests get stuck randomly on s390x for unknown reason. http://rubyci.s3.amazonaws.com/s390x/ruby-master/log/20211104T030003Z.fail.html.gz ``` [13715/21145] TestGCCompact#test_gc_compact_statstimeout: output interval exceeds 1800.0 seconds. ``` We spent some time to investigate this issue, but we can't figure out why, and it is unlikely that we'll be able to fix it anytime soon. This random failure makes the CI unuseful, so tentatively we suppress this test for a while. A contribution from those who are familiar with s390x is welcome. Notes: Merged: https://github.com/ruby/ruby/pull/5077
2021-08-02Stop infinite object allocation to get rid of OOM killerNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4697
2021-05-25Disable compaction on platforms that can't support itAaron Patterson
Manual compaction also requires a read barrier, so we need to disable even manual compaction on platforms that don't support mprotect. [Bug #17871] Notes: Merged: https://github.com/ruby/ruby/pull/4528
2021-04-09test/ruby/test_gc_compact.rb: Use assert_separately for debuggingYusuke Endoh
... the following timeout failure. http://rubyci.s3.amazonaws.com/rhel_zlinux/ruby-master/log/20210408T213303Z.fail.html.gz ``` [ 8871/21204] TestGCCompact#test_ast_compactstimeout: output interval exceeds 600.0 seconds. timeout: the process group 28416 is alive. PSOUT PGID PID ELAPSED %CPU VSZ COMMAND COMMAND PSOUT 28416 28416 12:46 0.0 108120 gmake gmake TESTS=--hide-skip -v RUBYOPT=-w test-all PSOUT 28416 28423 12:46 88.2 1446124 ruby ./test/runner.rb: TestGCCompact#test_ast_compacts timeout: INT signal sent. timeout: INT signal sent. timeout: TERM signal sent. timeout: TERM signal sent. timeout: KILL signal sent. ``` This error repeatedly occurs on RHEL s390x. This change sends SEGV when timeout occurs so that it should dump the backtrace.
2021-02-25Revert "Add tests for bug 17652"Aaron Patterson
This reverts commit a9920e7782f225b97e173a88640fe9e116b9964f.