summaryrefslogtreecommitdiff
path: root/gc/mmtk
AgeCommit message (Collapse)Author
2 days[ruby/mmtk] Implement object movement support for finalizer tablePeter Zhu
https://github.com/ruby/mmtk/commit/e5e2c1c347
3 days[ruby/mmtk] Clear slot when object is freedPeter Zhu
https://github.com/ruby/mmtk/commit/87290e45b2
7 days[ruby/mmtk] Assert that objects are not T_NONE in the write barrierPeter Zhu
https://github.com/ruby/mmtk/commit/59d27203e2
7 days[ruby/mmtk] Add MMTK_ASSERTPeter Zhu
https://github.com/ruby/mmtk/commit/e34d5cf32f
9 days[ruby/mmtk] Check that a and b are valid objects in write barrierPeter Zhu
https://github.com/ruby/mmtk/commit/350625ebb3
9 days[ruby/mmtk] Set MMTK_DEBUG in C compiler for debug buildsPeter Zhu
https://github.com/ruby/mmtk/commit/12a3904b04
10 days[ruby/mmtk] Assert pinning object is not movedPeter Zhu
https://github.com/ruby/mmtk/commit/8813e76bf8
12 days[ruby/mmtk] Process obj_free candidates in parallelPeter Zhu
Redos commit 544770d which seems to have accidentally been undone in b27d935.
12 daysAlso output GC thread backtrace in rb_mmtk_gc_thread_bugPeter Zhu
13 days[ruby/mmtk] Use rb_mmtk_gc_thread_bug for rb_mmtk_call_object_closurePeter Zhu
https://github.com/ruby/mmtk/commit/308936296a
13 days[ruby/mmtk] Propagate crash of GC thread to mutator threadPeter Zhu
This allows the mutator thread to dump its backtrace when a GC thread crashes. https://github.com/ruby/mmtk/commit/40ff9ffee7
13 days[ruby/mmtk] Check for T_NONE during markingPeter Zhu
https://github.com/ruby/mmtk/commit/c3e338bb25
13 days[ruby/mmtk] Assert target is not pinned during normal tracingPeter Zhu
https://github.com/ruby/mmtk/commit/58210c88ed
2026-01-01[ruby/mmtk] Format imports to be each on a new linePeter Zhu
https://github.com/ruby/mmtk/commit/42adba630e
2025-12-31Use `is_obj_encoding` instead of `is_data_encoding`Nobuyoshi Nakada
The argument to `is_data_encoding` is assumed to be `T_DATA`.
2025-12-31[ruby/mmtk] Split ProcessObjFreeCandidates to parallel and non-parallelPeter Zhu
This makes it easier to visualize in profilers which one is non-parallel. https://github.com/ruby/mmtk/commit/ba68b2ef3b
2025-12-31[ruby/mmtk] Process obj_free candidates in parallelPeter Zhu
This commit allows objects that are safe to be freed in parallel to do so. A decrease in object freeing time can be seen in profiles. The benchmarks don't show much difference. Before: -------------- -------------------- ---------- --------- bench sequential free (ms) stddev (%) RSS (MiB) activerecord 242.3 7.4 84.3 chunky-png 439.1 0.6 75.6 erubi-rails 1221.2 4.2 132.7 hexapdf 1544.8 1.8 429.1 liquid-c 42.7 7.4 48.5 liquid-compile 41.4 8.3 52.2 liquid-render 100.6 3.0 56.8 mail 108.9 2.1 65.1 psych-load 1536.9 0.6 43.4 railsbench 1633.5 2.6 146.2 rubocop 126.5 15.8 142.1 ruby-lsp 129.6 9.7 112.2 sequel 47.9 6.5 44.6 shipit 1152.0 2.7 315.2 -------------- -------------------- ---------- --------- After: -------------- ------------------ ---------- --------- bench parallel free (ms) stddev (%) RSS (MiB) activerecord 235.1 5.5 87.4 chunky-png 440.8 0.8 68.1 erubi-rails 1105.3 0.8 128.0 hexapdf 1578.3 4.1 405.1 liquid-c 42.6 7.1 48.4 liquid-compile 41.5 8.1 52.1 liquid-render 101.2 2.8 53.3 mail 109.7 2.7 64.8 psych-load 1567.7 1.1 44.4 railsbench 1644.9 1.9 150.9 rubocop 125.6 15.4 148.5 ruby-lsp 127.9 5.8 104.6 sequel 48.2 6.1 44.1 shipit 1215.3 4.7 320.5 -------------- ------------------ ---------- --------- https://github.com/ruby/mmtk/commit/4f0b5fd2eb
2025-12-30[ruby/mmtk] Use MMTK_HEAP_COUNT for SIZE_POOL_COUNTPeter Zhu
https://github.com/ruby/mmtk/commit/290a2aec4e
2025-12-30Add RVALUE_OLD_AGE to GC::INTERNAL_CONSTANTS for MMTkPeter Zhu
2025-12-29Implement moving Immix in MMTkPeter Zhu
This commit implements moving Immix in MMTk, which allows objects to move in the GC. The performance of this implementation is not yet amazing. It is very similar to non-moving Immix in many of them and slightly slower in others. The benchmark results is shown below. -------------- ----------------- ---------- --------- bench Moving Immix (ms) stddev (%) RSS (MiB) activerecord 241.9 0.5 86.6 chunky-png 447.8 0.8 74.9 erubi-rails 1183.9 0.8 136.1 hexapdf 1607.9 2.6 402.3 liquid-c 45.4 6.7 44.9 liquid-compile 44.1 9.3 53.0 liquid-render 105.4 4.5 55.9 lobsters 650.1 9.7 418.4 mail 115.4 2.1 64.4 psych-load 1656.8 0.8 43.6 railsbench 1653.5 1.3 149.8 rubocop 127.0 15.6 142.1 ruby-lsp 130.7 10.5 99.4 sequel 52.8 7.2 45.6 shipit 1187.0 3.9 311.0 -------------- ----------------- ---------- --------- -------------- --------------------- ---------- --------- bench Non-moving Immix (ms) stddev (%) RSS (MiB) activerecord 218.9 2.7 86.1 chunky-png 464.6 0.8 66.7 erubi-rails 1119.0 4.3 132.7 hexapdf 1539.8 1.8 425.2 liquid-c 40.6 6.9 45.2 liquid-compile 40.6 8.1 52.9 liquid-render 99.3 2.3 48.3 mail 107.4 5.3 65.4 psych-load 1535.6 1.0 39.5 railsbench 1565.6 1.1 149.6 rubocop 122.5 14.3 146.7 ruby-lsp 128.4 10.7 106.4 sequel 44.1 4.0 45.7 shipit 1154.5 2.7 358.5 -------------- --------------------- ---------- ---------
2025-12-26[ruby/mmtk] Fix cargo fmtPeter Zhu
https://github.com/ruby/mmtk/commit/f4c46cabc7
2025-12-25Implement declarative weak references in MMTkPeter Zhu
2025-12-22[ruby/mmtk] Implement Ruby heapPeter Zhu
This heap emulates the growth characteristics of the Ruby default GC's heap. By default, the heap grows by 40%, requires at least 20% empty after a GC, and allows at most 65% empty before it shrinks the heap. This is all configurable via the same environment variables the default GC uses (`RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO`, `RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO`, `RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO`, respectively). The Ruby heap can be enabled via the `MMTK_HEAP_MODE=ruby` environment variable. Compared to the dynamic heap in MMTk (which uses the MemBalancer algorithm), the Ruby heap allows the heap to grow more generously, which uses a bit more memory but offers significant performance gains because it runs GC much less frequently. We can see in the benchmarks below that this Ruby heap heap gives faster performance than the dynamic heap in every benchmark, with over 2x faster in many of them. We see that memory is often around 10-20% higher with certain outliers that use significantly more memory like hexapdf and erubi-rails. We can also see that this brings MMTk's Ruby heap much closer in performance to the default GC. Ruby heap benchmark results: -------------- -------------- ---------- --------- bench ruby heap (ms) stddev (%) RSS (MiB) activerecord 233.6 10.7 85.9 chunky-png 457.1 1.1 79.3 erubi-rails 1148.0 3.8 133.3 hexapdf 1570.5 2.4 403.0 liquid-c 42.8 5.3 43.4 liquid-compile 41.3 7.6 52.6 liquid-render 102.8 3.8 55.3 lobsters 651.9 8.0 426.3 mail 106.4 1.8 67.2 psych-load 1552.1 0.8 43.4 railsbench 1707.2 6.0 145.6 rubocop 127.2 15.3 148.8 ruby-lsp 136.6 11.7 113.7 sequel 47.2 5.9 44.4 shipit 1197.5 3.6 301.0 -------------- -------------- ---------- --------- Dynamic heap benchmark results: -------------- ----------------- ---------- --------- bench dynamic heap (ms) stddev (%) RSS (MiB) activerecord 845.3 3.1 76.7 chunky-png 525.9 0.4 38.9 erubi-rails 2694.9 3.4 115.8 hexapdf 2344.8 5.6 164.9 liquid-c 73.7 5.0 40.5 liquid-compile 107.1 6.8 40.3 liquid-render 147.2 1.7 39.5 lobsters 697.6 4.5 342.0 mail 224.6 2.1 64.0 psych-load 4326.7 0.6 37.4 railsbench 3218.0 5.5 124.7 rubocop 203.6 6.1 110.9 ruby-lsp 350.7 3.2 79.0 sequel 121.8 2.5 39.6 shipit 1510.1 3.1 220.8 -------------- ----------------- ---------- --------- Default GC benchmark results: -------------- --------------- ---------- --------- bench default GC (ms) stddev (%) RSS (MiB) activerecord 148.4 0.6 67.9 chunky-png 440.2 0.7 57.0 erubi-rails 722.7 0.3 97.8 hexapdf 1466.2 1.7 254.3 liquid-c 32.5 3.6 42.3 liquid-compile 31.2 1.9 35.4 liquid-render 88.3 0.7 30.8 lobsters 633.6 7.0 305.4 mail 76.6 1.6 53.2 psych-load 1166.2 1.3 29.1 railsbench 1262.9 2.3 114.7 rubocop 105.6 0.8 95.4 ruby-lsp 101.6 1.4 75.4 sequel 27.4 1.2 33.1 shipit 1083.1 1.5 163.4 -------------- --------------- ---------- --------- https://github.com/ruby/mmtk/commit/c0ca29922d
2025-12-21[ruby/mmtk] Add a 32 byte heap for allocating smaller objectsPeter Zhu
https://github.com/ruby/mmtk/commit/c4cca6c1c3
2025-12-20[ruby/mmtk] Implement fast path for bump pointer allocatorPeter Zhu
Adding a fast path for bump pointer allocator can improve allocation performance. For the following microbenchmark with MMTK_HEAP_MIN=100MiB: 10_000_000.times { String.new } Before: 810.7 ms ± 8.3 ms [User: 790.9 ms, System: 40.3 ms] After: 777.9 ms ± 10.4 ms [User: 759.0 ms, System: 37.9 ms] https://github.com/ruby/mmtk/commit/0ff5c9f579
2025-12-20[ruby/mmtk] Make rb_gc_impl_heap_id_for_size use MMTK_HEAP_COUNTPeter Zhu
https://github.com/ruby/mmtk/commit/2185189df4
2025-12-20[ruby/mmtk] Call rb_bug when Ruby mutator thread panicsPeter Zhu
This will allow the Ruby backtrace, memory mapping, etc. to be outputted when a Ruby mutator thread panics. https://github.com/ruby/mmtk/commit/d10fd325dd
2025-12-19[ruby/mmtk] Extract max object size to MMTK_MAX_OBJ_SIZEPeter Zhu
https://github.com/ruby/mmtk/commit/ed9036c295
2025-12-19[ruby/mmtk] Extract heap count to MMTK_HEAP_COUNT macroPeter Zhu
https://github.com/ruby/mmtk/commit/4e789e118b
2025-12-05Revert "gc.c: Pass shape_id to `newobj_init`"Peter Zhu
This reverts commit 228d13f6ed914d1e7f6bd2416e3f5be8283be865. This commit makes default.c and mmtk.c depend on shape.h, which prevents them from building independently.
2025-12-03gc.c: Pass shape_id to `newobj_init`Jean Boussier
Attempt to fix the following SEGV: ``` ruby(gc_mark) ../src/gc/default/default.c:4429 ruby(gc_mark_children+0x45) [0x560b380bf8b5] ../src/gc/default/default.c:4625 ruby(gc_mark_stacked_objects) ../src/gc/default/default.c:4647 ruby(gc_mark_stacked_objects_all) ../src/gc/default/default.c:4685 ruby(gc_marks_rest) ../src/gc/default/default.c:5707 ruby(gc_marks+0x4e7) [0x560b380c41c1] ../src/gc/default/default.c:5821 ruby(gc_start) ../src/gc/default/default.c:6502 ruby(heap_prepare+0xa4) [0x560b380c4efc] ../src/gc/default/default.c:2074 ruby(heap_next_free_page) ../src/gc/default/default.c:2289 ruby(newobj_cache_miss) ../src/gc/default/default.c:2396 ruby(RB_SPECIAL_CONST_P+0x0) [0x560b380c5df4] ../src/gc/default/default.c:2420 ruby(RB_BUILTIN_TYPE) ../src/include/ruby/internal/value_type.h:184 ruby(newobj_init) ../src/gc/default/default.c:2136 ruby(rb_gc_impl_new_obj) ../src/gc/default/default.c:2500 ruby(newobj_of) ../src/gc.c:996 ruby(rb_imemo_new+0x37) [0x560b380d8bed] ../src/imemo.c:46 ruby(imemo_fields_new) ../src/imemo.c:105 ruby(rb_imemo_fields_new) ../src/imemo.c:120 ``` I have no reproduction, but my understanding based on the backtrace and error is that GC is triggered inside `newobj_init` causing the new object to be marked while in a incomplete state. I believe the fix is to pass the `shape_id` down to `newobj_init` so it can be set before the GC has a chance to trigger.
2025-11-19[ruby/mmtk] Ensure not blocking for GC in rb_gc_impl_before_forkPeter Zhu
In rb_gc_impl_before_fork, it locks the VM and barriers all the Ractors before calling mmtk_before_fork. However, since rb_mmtk_block_for_gc is a barrier point, one or more Ractors could be paused there. However, mmtk_before_fork is not compatible with that because it assumes that the MMTk workers are idle, but the workers are not idle because they are busy working on a GC. This commit essentially implements a trylock. It will optimistically lock but will release the lock if it detects that any other Ractors are waiting in rb_mmtk_block_for_gc. For example, the following script demonstrates the issue: puts "Hello #{Process.pid}" 100.times do |i| puts "i = #{i}" Ractor.new(i) do |j| puts "Ractor #{j} hello" 1000.times do |i| s = "#{j}-#{i}" end Ractor.receive puts "Ractor #{j} goodbye" end pid = fork { } puts "Child pid is #{pid}" _, status = Process.waitpid2 pid puts status.success? end puts "Goodbye" We can see the MMTk worker thread is waiting to start the GC: #4 0x00007ffff66538b1 in rb_mmtk_stop_the_world () at gc/mmtk/mmtk.c:101 #5 0x00007ffff6d04caf in mmtk_ruby::collection::{impl#0}::stop_all_mutators<mmtk::scheduler::gc_work::{impl#14}::do_work::{closure_env#0}<mmtk::plan::immix::gc_work::ImmixGCWorkContext<mmtk_ruby::Ruby, 0>>> (_tls=..., mutator_visitor=...) at src/collection.rs:23 However, the mutator thread is stuck in mmtk_before_fork trying to stop that worker thread: #4 0x00007ffff6c0b621 in std::sys::thread::unix::Thread::join () at library/std/src/sys/thread/unix.rs:134 #5 0x00007ffff6658b6e in std::thread::JoinInner<()>::join<()> (self=...) #6 0x00007ffff6658d4c in std::thread::JoinHandle<()>::join<()> (self=...) #7 0x00007ffff665795e in mmtk_ruby::binding::RubyBinding::join_all_gc_threads (self=0x7ffff72462d0 <mmtk_ruby::BINDING+8>) at src/binding.rs:115 #8 0x00007ffff66561a8 in mmtk_ruby::api::mmtk_before_fork () at src/api.rs:309 #9 0x00007ffff66556ff in rb_gc_impl_before_fork (objspace_ptr=0x555555d17980) at gc/mmtk/mmtk.c:1054 #10 0x00005555556bbc3e in rb_gc_before_fork () at gc.c:5429 https://github.com/ruby/mmtk/commit/1a629504a7
2025-11-19[ruby/mmtk] Add VM barrier in rb_gc_impl_before_forkPeter Zhu
We need the VM barrier in rb_gc_impl_before_fork to stop the other Ractors because otherwise they could be allocating objects in the fast path which could be calling mmtk_add_obj_free_candidate. Since mmtk_add_obj_free_candidate acquires a lock on obj_free_candidates in weak_proc.rs, this lock may not be released in the child process after the Ractor dies. For example, the following script demonstrates the issue: puts "Hello #{Process.pid}" 100.times do |i| puts "i = #{i}" Ractor.new(i) do |j| puts "Ractor #{j} hello" 1000.times do |i| s = "#{j}-#{i}" end Ractor.receive puts "Ractor #{j} goodbye" end pid = fork { } puts "Child pid is #{pid}" _, status = Process.waitpid2 pid puts status.success? end puts "Goodbye" In the child process, we can see that it is stuck trying to acquire the lock on obj_free_candidates: #5 0x00007192bfb53f10 in mmtk_ruby::weak_proc::WeakProcessor::get_all_obj_free_candidates (self=0x7192c0657498 <mmtk_ruby::BINDING+72>) at src/weak_proc.rs:52 #6 0x00007192bfa634c3 in mmtk_ruby::api::mmtk_get_all_obj_free_candidates () at src/api.rs:295 #7 0x00007192bfa61d50 in rb_gc_impl_shutdown_call_finalizer (objspace_ptr=0x578c17abfc50) at gc/mmtk/mmtk.c:1032 #8 0x0000578c1601e48e in rb_ec_finalize (ec=0x578c17ac06d0) at eval.c:166 #9 rb_ec_cleanup (ec=<optimized out>, ex=<optimized out>) at eval.c:257 #10 0x0000578c1601ebf6 in ruby_cleanup (ex=<optimized out>) at eval.c:180 #11 ruby_stop (ex=<optimized out>) at eval.c:292 #12 0x0000578c16127124 in rb_f_fork (obj=<optimized out>) at process.c:4291 #13 rb_f_fork (obj=<optimized out>) at process.c:4281 https://github.com/ruby/mmtk/commit/eb4b229858
2025-11-14[ruby/mmtk] Lock VM in fork hooksPeter Zhu
If we are using multiple Ractors, other Ractors may allocate objects after rb_gc_impl_before_fork is ran because it does not lock the VM. This can cause the GC to be in a bad state since rb_gc_impl_before_fork may have terminated GC threads so a GC cannot run until rb_gc_impl_after_fork is ran. https://github.com/ruby/mmtk/commit/e4bea5676d
2025-11-09[ruby/mmtk] Lock the VM when freeing objects in ↵Peter Zhu
rb_gc_impl_shutdown_call_finalizer https://github.com/ruby/mmtk/commit/1828f6596f
2025-11-08Move rb_gc_verify_shareable to gc.cPeter Zhu
rb_gc_verify_shareable is not GC implementation specific so it should live in gc.c.
2025-10-31[ruby/mmtk] Bump mmtk-corePeter Zhu
https://github.com/ruby/mmtk/commit/9876d8f0a1
2025-10-23catch up modular-gcKoichi Sasada
2025-09-17Update rb_gc_impl_new_obj in mmtk.cPeter Zhu
2025-08-25Fix MMTk for compatibilityPeter Zhu
2025-07-30[ruby/mmtk] Skip weak references that are special constsPeter Zhu
If a reference marked weak becomes a special const, it will crash because it is not a GC handled object. We should skip special consts here. https://github.com/ruby/mmtk/commit/870a79426b
2025-07-29[ruby/mmtk] Fix warnings from cargo fmtPeter Zhu
https://github.com/ruby/mmtk/commit/84975a8840
2025-07-29[ruby/mmtk] Fix clippy warningsPeter Zhu
https://github.com/ruby/mmtk/commit/45f991578e
2025-06-13mmtk: Get rid of unused reference to FL_EXIVARJean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13610
2025-06-09Take file and line in GC VM locksPeter Zhu
This commit adds file and line to GC VM locking functions for debugging purposes and adds upper case macros to pass __FILE__ and __LINE__. Notes: Merged: https://github.com/ruby/ruby/pull/13550
2025-06-03Allow pass special constants to the write barrierPeter Zhu
Some GC implementations want to always know when an object is written to, even if the written value is a special constant. Checking special constants in rb_obj_written was a micro-optimization that made assumptions about the GC implementation. Notes: Merged: https://github.com/ruby/ruby/pull/13497
2025-05-30[ruby/mmtk] Fix environment variable parsingKunshan Wang
Ues more idiomatic rust approaches. https://github.com/ruby/mmtk/commit/ef125f9eae
2025-05-30[ruby/mmtk] Fix clippy warnings and formatting.Kunshan Wang
We also enable `#![warn(unsafe_op_in_unsafe_fn)]` in the whole mmtk_ruby crate. https://github.com/ruby/mmtk/commit/8b8025f71a
2025-05-30[ruby/mmtk] Bump MMTk and dependencies versionKunshan Wang
https://github.com/ruby/mmtk/commit/de252637ec
2025-05-30[ruby/mmtk] Remove unused constantKunshan Wang
Remove the unused constant HAS_MOVED_GFIELDSTBL and related methods. In the mmtk/mmtk-ruby repo, we are now able to find the global field (IV) table of a moved object during copying GC without using the HAS_MOVED_GFIELDSTBL bit. We synchronize some of the code, although we haven't implemented moving GC in ruby/mmtk, yet. See: https://github.com/mmtk/mmtk-ruby/commit/13080acdf553f20a88a7ea9ab9f6877611017136 https://github.com/ruby/mmtk/commit/400ba4e747