Commit graph

78 commits

Author SHA1 Message Date
Peter Zhu
f6e829603e Removed unused macro RVALUE_PAGE_MARKED 2024-08-01 15:54:08 -04:00
git
cb5c460594 * expand tabs. [ci skip]
Please consider using misc/expand_tabs.rb as a pre-commit hook.
2024-07-26 15:44:44 +00:00
Alan Wu
158177e399 Improve allocation throughput by outlining cache miss code path
Previously, GCC 11 on x86-64 inlined the heavy weight logic for
potentially triggering GC into newobj_alloc(). This slowed down
the hotter code path where the ractor cache hits, causing a degradation
to allocation throughput.

Outline the logic into a separate function and have it never inlined.

This restores allocation throughput to the same level as
98eeadc ("Development of 3.4.0 started.").

To evaluate, instrument miniruby so it allocates a bunch of objects and
then exits:

    diff --git a/eval.c b/eval.c
    --- a/eval.c
    +++ b/eval.c
    @@ -92,6 +92,15 @@ ruby_setup(void)
         }
         EC_POP_TAG();

    +rb_gc_disable();
    +rb_execution_context_t *ec = GET_EC();
    +long const n = 20000000;
    +for (long i = 0; i < n; ++i) {
    +    rb_wb_protected_newobj_of(ec, 0, T_OBJECT, 40);
    +}
    +printf("alloc %ld\n", n);
    +exit(0);
    +
         return state;
     }

With `3.3-equiv` being 98eeadc, and `pre` being f2728c3393
and `post` being this commit, I have:

    $ hyperfine -L buildtag post,pre,3.3-equiv '/ruby/build-{buildtag}/miniruby'
    Benchmark 1: /ruby/build-post/miniruby
      Time (mean ± σ):     873.4 ms ±   2.8 ms    [User: 377.6 ms, System: 490.2 ms]
      Range (min … max):   868.3 ms … 877.8 ms    10 runs

    Benchmark 2: /ruby/build-pre/miniruby
      Time (mean ± σ):     960.1 ms ±   2.8 ms    [User: 430.8 ms, System: 523.9 ms]
      Range (min … max):   955.5 ms … 964.2 ms    10 runs

    Benchmark 3: /ruby/build-3.3-equiv/miniruby
      Time (mean ± σ):     886.9 ms ±   2.8 ms    [User: 379.5 ms, System: 501.0 ms]
      Range (min … max):   883.0 ms … 890.8 ms    10 runs

    Summary
      '/ruby/build-post/miniruby' ran
        1.02 ± 0.00 times faster than '/ruby/build-3.3-equiv/miniruby'
        1.10 ± 0.00 times faster than '/ruby/build-pre/miniruby'

These results are from a Skylake server with GCC 11.
2024-07-26 11:44:34 -04:00
Alan Wu
0ada02abe2 Put the default GC implementation back into gc.o
We discovered that having gc.o and gc_impl.o in separate translation
units diminishes codegen quality with GCC 11 on x86-64. This commit
solves that problem by including default/gc.c into gc.c, letting the
optimizer have visibility into the body of functions again in builds
not using link-time optimization, which are common.

This effectively restores things to the way they were before
[Feature #20470] from the optimizer's perspective while maintaining the
ability to build gc/default.c as a DSO.

There were a few functions duplicated across gc.c and gc/default.c.
Extract them and put them into gc/gc.h.
2024-07-26 11:44:34 -04:00
Alan Wu
cef959df90 Delete unused rb_gc_impl_get_finalizers() not in gc_impl.h 2024-07-26 11:44:34 -04:00
Alan Wu
83b0cedffe Add branch prediction annotations for object allocation
I get a slight boost from these with GCC 11 on Intel Skylake.

Part of a larger story to fix an allocation throughput regression
compared to 98eeadc ("Development of 3.4.0 started.") as the baseline.
2024-07-25 12:46:33 -04:00
Peter Zhu
0a9f771e19 Don't check live slot count when multi-Ractor 2024-07-24 09:44:54 -04:00
Peter Zhu
6770bb4a8c Fix running GC in finalizer when RUBY_FREE_AT_EXIT
The following code crashes because the GC ran during finalizers will
cause T_ZOMBIE objects to be on the heap, which crashes when we call
rb_gc_obj_free on it:

    raise_proc = proc do |id|
      GC.start
    end
    1000.times do
      ObjectSpace.define_finalizer(Object.new, raise_proc)
    end
2024-07-23 14:45:45 -04:00
Peter Zhu
51505f70e3 Move frozen check out of rb_gc_impl_undefine_finalizer 2024-07-19 08:53:32 -04:00
Peter Zhu
4b05d2dbb0 Make rb_gc_impl_undefine_finalizer return void 2024-07-19 08:53:32 -04:00
Peter Zhu
57d9b8ee07 Assert that object is not frozen in rb_gc_impl_define_finalizer 2024-07-19 08:53:32 -04:00
Peter Zhu
e8aa9daa5b Move return value of rb_define_finalizer out
Moves return value logic of rb_define_finalizer out from
rb_gc_impl_define_finalizer.
2024-07-19 08:53:32 -04:00
Peter Zhu
d6ef74407b Use rb_obj_hide instead of setting klass to 0 2024-07-18 13:47:00 -04:00
Peter Zhu
573c2893dc Don't disable GC in rb_gc_impl_object_id
Disabling GC when creating the object ID was introduced in commit
67b2c21, but we shouldn't need to disable the GC.
2024-07-17 15:46:41 -04:00
Peter Zhu
403f44ec2c Make OBJ_ID_INCREMENT == RUBY_IMMEDIATE_MASK + 1
All the non-GC objects (i.e. immediates) have addresses such that
`obj % RUBY_IMMEDIATE_MASK != 0` (except for `Qfalse`, which is 0). We
can define `OBJ_ID_INCREMENT` as `RUBY_IMMEDIATE_MASK + 1` which should
guarantee that GC objects never have conflicting object IDs with
immediates.
2024-07-17 09:01:42 -04:00
Matt Valentine-House
690ea013ca Remove unused variable from GC compaction path 2024-07-17 12:47:27 +01:00
Peter Zhu
4fe3082b63 [DOC] Fix typo in gc/default.c 2024-07-16 09:55:48 -04:00
Peter Zhu
93489d536b Remove dependency on dtrace when building shared GC 2024-07-16 09:09:41 -04:00
卜部昌平
a887b41875 static const char *type_name() implemented
The function body was missing.
2024-07-16 13:09:19 +09:00
卜部昌平
963059a8d2 fix compile error 2024-07-16 13:09:19 +09:00
Peter Zhu
2245f278d3 Remove unused ruby_initial_gc_stress 2024-07-15 11:28:00 -04:00
Peter Zhu
461a7b8316 Add gc/gc.h for functions in gc.c and used by GC implementations 2024-07-15 08:57:14 -04:00
Matt Valentine-House
8418df72ec Avoid extra module linkage in gc/default.c
We don't need to use rb_str_to_cstr here, which means we don't need to
include string headers anymore.
2024-07-12 14:43:33 +01:00
Matt Valentine-House
4d77803a66 Rename full_mark -> rgengc_allow_full_mark 2024-07-12 14:43:33 +01:00
Matt Valentine-House
f543c68e1c Provide GC.config to disable major GC collections
This feature provides a new method `GC.config` that configures internal
GC configuration variables provided by an individual GC implementation.

Implemented in this PR is the option `full_mark`: a boolean value that
will determine whether the Ruby GC is allowed to run a major collection
while the process is running.

It has the following semantics

This feature configures Ruby's GC to only run minor GC's. It's designed
to give users relying on Out of Band GC complete control over when a
major GC is run. Configuring `full_mark: false` does two main things:

* Never runs a Major GC. When the heap runs out of space during a minor
  and when a major would traditionally be run, instead we allocate more
  heap pages, and mark objspace as needing a major GC.
* Don't increment object ages. We don't promote objects during GC, this
  will cause every object to be scanned on every minor. This is an
  intentional trade-off between minor GC's doing more work every time,
  and potentially promoting objects that will then never be GC'd.

The intention behind not aging objects is that users of this feature
should use a preforking web server, or some other method of pre-warming
the oldgen (like Nakayoshi fork)before disabling Majors. That way most
objects that are going to be old will have already been promoted.

This will interleave major and minor GC collections in exactly the same
what that the Ruby GC runs in versions previously to this. This is the
default behaviour.

* This new method has the following extra semantics:
  - `GC.config` with no arguments returns a hash of the keys of the
    currently configured GC
  - `GC.config` with a key pair (eg. `GC.config(full_mark: true)` sets
    the matching config key to the corresponding value and returns the
    entire known config hash, including the new values. If the key does
    not exist, `nil` is returned

* When a minor GC is run, Ruby sets an internal status flag to determine
  whether the next GC will be a major or a minor. When `full_mark:
  false` this flag is ignored and every GC will be a minor.

  This status flag can be accessed at
  `GC.latest_gc_info(:needs_major_by)`. Any value other than `nil` means
  that the next collection would have been a major.

  Thus it's possible to use this feature to check at a predetermined
  time, whether a major GC is necessary and run one if it is. eg. After
  a request has finished processing.

  ```ruby
  if GC.latest_gc_info(:needs_major_by)
    GC.start(full_mark: true)
  end
  ```

[Feature #20443]
2024-07-12 14:43:33 +01:00
Peter Zhu
00d0ddd48a Add gc/gc_impl.h for GC implementation headers 2024-07-12 08:41:33 -04:00
卜部昌平
fa6bf1da57 give up USE_GC_MALLOC_OBJ_INFO_DETAILS
This feature is no longer possible under current design; now that our GC
is pluggable, we cannot assume what was achieved by this compiler flag
is always possble by the dynamically-loaded GC implementation.
2024-07-12 10:21:07 +09:00
Peter Zhu
a0469a4788 Rename gc/gc_impl.c to gc/default.c
Changing the name makes it clear that this is the default GC in Ruby.
2024-07-11 09:09:47 -04:00
Renamed from gc/gc_impl.c (Browse further)