#126 Define the GC compaction support during run time.
Merged 2 years ago by jackorp. Opened 2 years ago by jackorp.
rpms/ jackorp/ruby detect-compaction-support  into  rawhide

@@ -0,0 +1,293 @@ 

+ From 4d9cc9afa47981520d991d19fd78b322f1ba9f2a Mon Sep 17 00:00:00 2001

+ From: Jarek Prokop <jprokop@redhat.com>

+ Date: Wed, 22 Jun 2022 01:03:49 +0200

+ Subject: [PATCH] Detect compaction support during runtime.

+ 

+ The patch is created by backporting 3 commits from

+ the upstream Ruby master branch in the chronological order below.

+ 

+ https://github.com/ruby/ruby/commit/52d42e702375446746164a0251e1a10bce813b78

+ https://github.com/ruby/ruby/commit/79eaaf2d0b641710613f16525e4b4c439dfe854e

+ https://github.com/ruby/ruby/commit/2c190863239bee3f54cfb74b16bb6ea4cae6ed20

+ 

+ == How to create this patch ==

+ 

+ Download Ruby source code.

+ ```

+ $ git clone https://github.com/ruby/ruby.git

+ $ cd ruby

+ ```

+ 

+ First create a commit squashed from the 3 commits above.

+ Checkout the second commmit above, and create a temporary branch.

+ ```

+ $ git checkout 79eaaf2d0b641710613f16525e4b4c439dfe854e

+ $ git checkout -b wip/detect-compaction-runtime-tmp

+ ```

+ 

+ Cherry pick the third commit on the second commit.

+ ```

+ $ git cherry-pick 2c190863239bee3f54cfb74b16bb6ea4cae6ed20

+ ```

+ 

+ Squash the last 3 commits on the branch.

+ ```

+ $ git rebase -i 2223eb082afa6d05321b69df783d4133b9aacba6

+ ```

+ 

+ Then checkout Ruby 3.1.2 branch.

+ Create a new branch.

+ Merge the Fedora Ruby's

+ ruby-3.2.0-define-unsupported-gc-compaction-methods-as-rb_f_notimplement.patch.

+ ```

+ $ git checkout v3_1_2

+ $ git checkout -b wip/detect-compaction-runtime

+ $ patch -p1 <

+ ~/fed/ruby/ruby-3.2.0-define-unsupported-gc-compaction-methods-as-rb_f_notimplement.patch

+ $ git add gc.c gc.rb test/ruby/test_gc_compact.rb

+ $ git commit

+ ```

+ 

+ Merge the squashed one commit on the

+ `wip/detect-compaction-runtime-tmp` branch

+ into the `wip/detect-compaction-runtime` branch.

+ ```

+ $ git cherry-pick <the squashed commit above>

+ ```

+ 

+ Fix conflicts seeing the difference by `git show <the squashed commit

+ above>`

+ on another terminal.

+ ```

+ $ vi gc.c

+ $ git add gc.c

+ $ git commit

+ ```

+ 

+ == Notes for the patch ==

+ 

+ ```

+ +# define GC_COMPACTION_SUPPORTED (GC_CAN_COMPILE_COMPACTION && USE_MMAP_ALIGNED_ALLOC)

+ ```

+ 

+ We use the USE_MMAP_ALIGNED_ALLOC instead of HEAP_PAGE_ALLOC_USE_MMAP on

+ the line above. Because while the Ruby on the master branch replaced the

+ USE_MMAP_ALIGNED_ALLOC with HEAP_PAGE_ALLOC_USE_MMAP, Ruby 3.1.2 doesn't.

+ See <https://github.com/ruby/ruby/commit/fe21b7794af0cdb7ebd502e2c0da38c68fd89839>.

+ 

+ 

+ ```

+ +        rb_define_singleton_method(rb_mGC, "verify_compaction_references", gc_verify_compaction_references, -1);

+ ```

+ 

+ We added the line in the case that GC_COMPACTION_SUPPORTED is true.

+ Because while the Ruby on the master branch defines the

+ GC.verify_compaction_references in the gc.rb in

+ the case that GC_COMPACTION_SUPPORTED is true, Ruby 3.1.2

+ doesn't define it in the gc.rb.

+ See <https://github.com/ruby/ruby/commit/b96a3a6fd2093e1dbea5491c002da515652dd347>.

+ 

+ 

+ ```

+ +	OPT(GC_COMPACTION_SUPPORTED);

+ ```

+ 

+ We added the line to expose the C macro to Ruby level.

+ In Ruby the macro existance can then be checked like so:

+ ```Ruby

+ GC::OPTS.include?("GC_COMPACTION_SUPPORTED")

+ ```

+ It will return `true` if the GC_COMPACTION_SUPPORTED evaluates to `true` on the

+ C level, `false` otherwise.

+ See <https://github.com/ruby/ruby/blob/b96a3a6fd2093e1dbea5491c002da515652dd347/gc.c#L14091>

+ 

+ == Original commit messages ==

+ 

+ This is a combination of 3 commits.

+ This is the 1st commit message:

+ ~~~

+ Rename GC_COMPACTION_SUPPORTED

+ 

+ Naming this macro GC_COMPACTION_SUPPORTED is misleading because it

+ only checks whether compaction is supported at compile time.

+ 

+ [Bug #18829]

+ ~~~

+ 

+ This is the commit message #2:

+ ~~~

+ Include runtime checks for compaction support

+ 

+ Commit 0c36ba53192c5a0d245c9b626e4346a32d7d144e changed GC compaction

+ methods to not be implemented when not supported. However, that commit

+ only does compile time checks (which currently only checks for WASM),

+ but there are additional compaction support checks during run time.

+ 

+ This commit changes it so that GC compaction methods aren't defined

+ during run time if the platform does not support GC compaction.

+ 

+ [Bug #18829]

+ ~~~

+ 

+ This is the commit message #3:

+ ~~~

+ Suppress code unused unless GC_CAN_COMPILE_COMPACTION

+ ~~~

+ ---

+  gc.c | 63 +++++++++++++++++++++++++++++++++++++++++-------------------

+  1 file changed, 43 insertions(+), 20 deletions(-)

+ 

+ diff --git a/gc.c b/gc.c

+ index 1c35856c44..bff0666a17 100644

+ --- a/gc.c

+ +++ b/gc.c

+ @@ -4980,6 +4980,23 @@ gc_unprotect_pages(rb_objspace_t *objspace, rb_heap_t *heap)

+  static void gc_update_references(rb_objspace_t * objspace);

+  static void invalidate_moved_page(rb_objspace_t *objspace, struct heap_page *page);

+  

+ +#ifndef GC_CAN_COMPILE_COMPACTION

+ +#if defined(__wasi__) /* WebAssembly doesn't support signals */

+ +# define GC_CAN_COMPILE_COMPACTION 0

+ +#else

+ +# define GC_CAN_COMPILE_COMPACTION 1

+ +#endif

+ +#endif

+ +

+ +#if defined(__MINGW32__) || defined(_WIN32)

+ +# define GC_COMPACTION_SUPPORTED 1

+ +#else

+ +/* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for

+ + * the read barrier, so we must disable compaction. */

+ +# define GC_COMPACTION_SUPPORTED (GC_CAN_COMPILE_COMPACTION && USE_MMAP_ALIGNED_ALLOC)

+ +#endif

+ +

+ +#if GC_CAN_COMPILE_COMPACTION

+  static void

+  read_barrier_handler(uintptr_t address)

+  {

+ @@ -5000,6 +5017,7 @@ read_barrier_handler(uintptr_t address)

+      }

+      RB_VM_LOCK_LEAVE();

+  }

+ +#endif

+  

+  #if defined(_WIN32)

+  static LPTOP_LEVEL_EXCEPTION_FILTER old_handler;

+ @@ -9250,13 +9268,7 @@ gc_start_internal(rb_execution_context_t *ec, VALUE self, VALUE full_mark, VALUE

+  

+      /* For now, compact implies full mark / sweep, so ignore other flags */

+      if (RTEST(compact)) {

+ -        /* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for

+ -         * the read barrier, so we must disable compaction. */

+ -#if !defined(__MINGW32__) && !defined(_WIN32)

+ -        if (!USE_MMAP_ALIGNED_ALLOC) {

+ -            rb_raise(rb_eNotImpError, "Compaction isn't available on this platform");

+ -        }

+ -#endif

+ +        GC_ASSERT(GC_COMPACTION_SUPPORTED);

+  

+          reason |= GPR_FLAG_COMPACT;

+      }

+ @@ -9421,7 +9433,7 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, size_t slot_size)

+      return (VALUE)src;

+  }

+  

+ -#if GC_COMPACTION_SUPPORTED

+ +#if GC_CAN_COMPILE_COMPACTION

+  static int

+  compare_free_slots(const void *left, const void *right, void *dummy)

+  {

+ @@ -10149,7 +10161,7 @@ gc_update_references(rb_objspace_t *objspace)

+      gc_update_table_refs(objspace, finalizer_table);

+  }

+  

+ -#if GC_COMPACTION_SUPPORTED

+ +#if GC_CAN_COMPILE_COMPACTION

+  /*

+   *  call-seq:

+   *     GC.latest_compact_info -> {:considered=>{:T_CLASS=>11}, :moved=>{:T_CLASS=>11}}

+ @@ -10190,7 +10202,7 @@ gc_compact_stats(VALUE self)

+  #  define gc_compact_stats rb_f_notimplement

+  #endif

+  

+ -#if GC_COMPACTION_SUPPORTED

+ +#if GC_CAN_COMPILE_COMPACTION

+  static void

+  root_obj_check_moved_i(const char *category, VALUE obj, void *data)

+  {

+ @@ -10269,7 +10281,7 @@ gc_compact(VALUE self)

+  #  define gc_compact rb_f_notimplement

+  #endif

+  

+ -#if GC_COMPACTION_SUPPORTED

+ +#if GC_CAN_COMPILE_COMPACTION

+  /*

+   * call-seq:

+   *    GC.verify_compaction_references(toward: nil, double_heap: false) -> hash

+ @@ -10800,7 +10812,7 @@ gc_disable(rb_execution_context_t *ec, VALUE _)

+      return rb_gc_disable();

+  }

+  

+ -#if GC_COMPACTION_SUPPORTED

+ +#if GC_CAN_COMPILE_COMPACTION

+  /*

+   *  call-seq:

+   *     GC.auto_compact = flag

+ @@ -10814,8 +10826,7 @@ gc_disable(rb_execution_context_t *ec, VALUE _)

+  static VALUE

+  gc_set_auto_compact(VALUE _, VALUE v)

+  {

+ -    /* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for

+ -     * the read barrier, so we must disable automatic compaction. */

+ +    GC_ASSERT(GC_COMPACTION_SUPPORTED);

+  

+      ruby_enable_autocompact = RTEST(v);

+      return v;

+ @@ -10824,7 +10835,8 @@ gc_set_auto_compact(VALUE _, VALUE v)

+  #  define gc_set_auto_compact rb_f_notimplement

+  #endif

+  

+ -#if GC_COMPACTION_SUPPORTED

+ +

+ +#if GC_CAN_COMPILE_COMPACTION

+  /*

+   *  call-seq:

+   *     GC.auto_compact    -> true or false

+ @@ -13696,11 +13708,21 @@ Init_GC(void)

+      rb_define_singleton_method(rb_mGC, "malloc_allocated_size", gc_malloc_allocated_size, 0);

+      rb_define_singleton_method(rb_mGC, "malloc_allocations", gc_malloc_allocations, 0);

+  #endif

+ -    rb_define_singleton_method(rb_mGC, "compact", gc_compact, 0);

+ -    rb_define_singleton_method(rb_mGC, "auto_compact", gc_get_auto_compact, 0);

+ -    rb_define_singleton_method(rb_mGC, "auto_compact=", gc_set_auto_compact, 1);

+ -    rb_define_singleton_method(rb_mGC, "latest_compact_info", gc_compact_stats, 0);

+ -    rb_define_singleton_method(rb_mGC, "verify_compaction_references", gc_verify_compaction_references, -1);

+ +    if (GC_COMPACTION_SUPPORTED) {

+ +        rb_define_singleton_method(rb_mGC, "compact", gc_compact, 0);

+ +        rb_define_singleton_method(rb_mGC, "auto_compact", gc_get_auto_compact, 0);

+ +        rb_define_singleton_method(rb_mGC, "auto_compact=", gc_set_auto_compact, 1);

+ +        rb_define_singleton_method(rb_mGC, "latest_compact_info", gc_compact_stats, 0);

+ +        rb_define_singleton_method(rb_mGC, "verify_compaction_references", gc_verify_compaction_references, -1);

+ +    }

+ +    else {

+ +        rb_define_singleton_method(rb_mGC, "compact", rb_f_notimplement, 0);

+ +        rb_define_singleton_method(rb_mGC, "auto_compact", rb_f_notimplement, 0);

+ +        rb_define_singleton_method(rb_mGC, "auto_compact=", rb_f_notimplement, 1);

+ +        rb_define_singleton_method(rb_mGC, "latest_compact_info", rb_f_notimplement, 0);

+ +        /* When !GC_COMPACTION_SUPPORTED, this method is not defined in gc.rb */

+ +        rb_define_singleton_method(rb_mGC, "verify_compaction_references", rb_f_notimplement, -1);

+ +    }

+  

+  #if GC_DEBUG_STRESS_TO_CLASS

+      rb_define_singleton_method(rb_mGC, "add_stress_to_class", rb_gcdebug_add_stress_to_class, -1);

+ @@ -13724,6 +13746,7 @@ Init_GC(void)

+  	OPT(MALLOC_ALLOCATED_SIZE);

+  	OPT(MALLOC_ALLOCATED_SIZE_CHECK);

+  	OPT(GC_PROFILE_DETAIL_MEMORY);

+ +	OPT(GC_COMPACTION_SUPPORTED);

+  #undef OPT

+  	OBJ_FREEZE(opts);

+      }

+ -- 

+ 2.36.1

+ 

file modified
+10 -7
@@ -22,7 +22,7 @@ 

  %endif

  

  

- %global release 165

+ %global release 166

  %{!?release_string:%define release_string %{?development_release:0.}%{release}%{?development_release:.%{development_release}}%{?dist}}

  

  # The RubyGems library has to stay out of Ruby directory tree, since the
@@ -187,6 +187,11 @@ 

  # diff -u {ruby-3.1.2,ruby}/gc.rbinc > ruby-3.2.0-define-unsupported-gc-compaction-methods_generated-files.patch

  # diff -u {ruby-3.1.2,ruby}/miniprelude.c >> ruby-3.2.0-define-unsupported-gc-compaction-methods_generated-files.patch

  Patch23: ruby-3.2.0-define-unsupported-gc-compaction-methods_generated-files.patch

+ # Define the GC compaction support macro at run time.

+ # https://bugs.ruby-lang.org/issues/18829

+ # https://github.com/ruby/ruby/pull/6019

+ # https://github.com/ruby/ruby/commit/2c190863239bee3f54cfb74b16bb6ea4cae6ed20

+ Patch24: ruby-3.2.0-Detect-compaction-support-during-runtime.patch

  

  Requires: %{name}-libs%{?_isa} = %{version}-%{release}

  Suggests: rubypick
@@ -661,6 +666,7 @@ 

  %patch21 -p1

  %patch22 -p1

  %patch23 -p1

+ %patch24 -p1

  

  # Provide an example of usage of the tapset:

  cp -a %{SOURCE3} .
@@ -668,12 +674,6 @@ 

  %build

  autoconf

  

- # Some platforms do not support compaction and upstream does not seem to provide the

- # right mechanism for the enablement of the preprocessor macros.

- # https://bugs.ruby-lang.org/issues/18829

- %ifnarch ppc64le

- CFLAGS="%{build_cflags} -DGC_COMPACTION_SUPPORTED"

- %endif

  %configure \

          --with-rubylibprefix='%{ruby_libdir}' \

          --with-archlibdir='%{_libdir}' \
@@ -1523,6 +1523,9 @@ 

  

  

  %changelog

+ * Thu Jun 16 2022 Jarek Prokop <jprokop@redhat.com> - 3.1.2-166

+ - Detect compaction support during run time.

+ 

  * Tue Jun 07 2022 Jarek Prokop <jprokop@redhat.com> - 3.1.2-165

  - Define GC compaction methods as rb_f_notimplement on unsupported platforms.

  

Upstream commit 0c36ba5 [0] changed GC compaction methods to not be implemented
when not supported. However, that commit only does compile time checks (which
currently only checks for WASM), but there are additional compaction
support checks during run time.

This commit changes it so that GC compaction methods aren't defined
during run time if the platform does not support GC compaction.

[0] https://github.com/ruby/ruby/commit/0c36ba53192c5a0d245c9b626e4346a32d7d144e
Related PR: https://github.com/ruby/ruby/pull/6019
Related upstream issue: https://bugs.ruby-lang.org/issues/18829


Tested on ppc64le with RPMs from this build: https://koji.fedoraproject.org/koji/taskinfo?taskID=88322779
With the following reproducer:

count = 0

begin
  GC.verify_compaction_references(double_heap: true, toward: :empty)
rescue NotImplementedError => e
  count += 1
  puts e
end

[:compact, :auto_compact, :latest_compact_info].each do |meth|
  begin
   GC.send(meth)
  rescue NotImplementedError => e
    count += 1
    puts e
  end
end

100_000.times do |i|
  puts "i: #{i}, count: #{count}"
end

The output of the script is as expected:

$ ruby reproducer.rb | head -n 10
verify_compaction_references() function is unimplemented on this machine
compact() function is unimplemented on this machine
auto_compact() function is unimplemented on this machine
latest_compact_info() function is unimplemented on this machine
i: 0, count: 4
i: 1, count: 4
i: 2, count: 4
i: 3, count: 4
i: 4, count: 4
i: 5, count: 4

Locally, this reproducer with the same build on x86_64 (on my local machine in a Rawhide container) raises no exception and the count variable has a value of 0, as is expected since compaction is supported on 64bit x86 platforms.


There is a difference after backporting the patch that differs from the upstream.
This part https://github.com/ruby/ruby/pull/6019/files#diff-d1cee85c3b0e24a64519c11150abe26fd0b5d8628a23d356dd0b535ac4595d49R14131
has an additional line in our downstreamed patch:
namely this one: https://src.fedoraproject.org/fork/jackorp/rpms/ruby/blob/detect-compaction-support/f/ruby-3.2.0-detect_compaction_support_during_runtime.patch#_159

This is because of not including this commit in the last PR regarding GC compaction: https://github.com/ruby/ruby/commit/b96a3a6fd2093e1dbea5491c002da515652dd347

rebased onto 144e0b207e657bef23943d8fc1cc81cb649864f2

2 years ago

Thanks for the PR. Before reviewing this PR, I want to see the ruby-3.1.2-165.fc37 including your previous PR on the rawhide. Are you still building it?

Currently the rawhide build is still ruby-3.1.2-164.fc37.
https://src.fedoraproject.org/rpms/ruby

Before reviewing this PR, I want to see the ruby-3.1.2-165.fc37 including your previous PR on the rawhide. Are you still building it?

I had a successful build around yesterday morning (auto rawhide update linked): https://bodhi.fedoraproject.org/updates/FEDORA-2022-3090a345d8

The attached build: https://koji.fedoraproject.org/koji/buildinfo?buildID=1984862

Currently the rawhide build is still ruby-3.1.2-164.fc37.

It will probably take some time until it propagates everywhere, however the update I linked was submitted for stable by bodhi.

It will probably take some time until it propagates everywhere, however the update I linked was submitted for stable by bodhi.

Ah, all right. I found it.
https://bodhi.fedoraproject.org/updates/FEDORA-2022-3090a345d8

However, we might want to review the proposed patch (and/or wait at least until tomorrow) before going forward as there is a thread on the PR where the preprocessor conditions are kept instead of being removed:
https://github.com/ruby/ruby/pull/6019#discussion_r899165154

Theoretically, we do not need it, since most of the compile time compaction checks were removed in favor of run time checks.

rebased onto 5fc6be7b95e6d12b0ef14ccce2d264ef39f9f032

2 years ago

I chose to apply the upstream patch from the PR's discussion [0] as it reached the main Ruby branch and it unimplements methods when compaction is not supported

I have made some scratch builds but most of them failed on similar, tests as the previous ones, IOW nothing new, so most probably unrelated failures we have been observing for some time.

This one can be taken as an example of a successful build of a platform supporting compaction (e.g. x86_64) and a platform not supporting compaction (e.g. ppc64le): https://koji.fedoraproject.org/koji/taskinfo?taskID=88360074

As mentioned on the GitHub ticket [1], I have confirmed that the patch works and Ruby behaves as expected even on ppc64le and we no longer have a need for the build-arch conditional.

This PR is now ready for review.

[0] https://github.com/ruby/ruby/pull/6019#discussion_r899165154
[1] https://github.com/ruby/ruby/pull/6019#issuecomment-1157717487

Build succeeded.

How did you create the patch ruby-3.2.0-detect_compaction_support_during_runtime.patch?

It is different from https://github.com/ruby/ruby/commit/79eaaf2d0b641710613f16525e4b4c439dfe854e.

I don't understand which upstream commit is used for the patch, and I don't understand why the https://github.com/ruby/ruby/commit/2c190863239bee3f54cfb74b16bb6ea4cae6ed20 above on the comment is related to the Patch24, and on the comment.

And seeing comments for the other patches. The order is first https://bugs.ruby-lang.org , then second https://github.com/ruby/ruby/ .

# https://bugs.ruby-lang.org/issues/18829
# https://github.com/ruby/ruby/...

I also see the ruby-3.2.0-detect_compaction_support_during_runtime.patch doesn't have git meta data. It's better to have it possible.

LGTM. I've checked the patch and built it in my COPR:

https://copr.fedorainfracloud.org/coprs/build/4548202


Just my comments, from what I've understood as I've discussed with @jackorp:

How did you create the patch ruby-3.2.0-detect_compaction_support_during_runtime.patch?

It's based on the commit bellow. However other commits are not referenced (and probably not used), as the change is aiming to be minimal.

It is different from https://github.com/ruby/ruby/commit/79eaaf2d0b641710613f16525e4b4c439dfe854e.

Yes, some additional bits needed to be backported for the patch to be complete (and compatible) for our use-case.

I don't understand which upstream commit is used for the patch, and I don't understand why the https://github.com/ruby/ruby/commit/2c190863239bee3f54cfb74b16bb6ea4cae6ed20 above on the comment is related to the Patch24, and on the comment.

And seeing comments for the other patches. The order is first https://bugs.ruby-lang.org , then second https://github.com/ruby/ruby/ .

I don't understand the meaning of your statement. Could you explain in what way does the order matter?

```

https://bugs.ruby-lang.org/issues/18829

https://github.com/ruby/ruby/...

```

I also see the ruby-3.2.0-detect_compaction_support_during_runtime.patch doesn't have git meta data. It's better to have it possible.

FTR: git metadata is something I've never used and probably not related to our use, as there's none in our repository:

$ git notes 
<blank>

Or do you mean standard git commit message? I don't usually comment on patches. Is it required?

How did you create the patch ruby-3.2.0-detect_compaction_support_during_runtime.patch?

Manual backport. There are not that many changed lines of code and applying the patch via git results in merge conflicts, which were more trouble resolving than worth (as there were nontrivial chunks of differences), I deemed it to be safer (and easier for me) to backport by hand than to attempt to resolve the merge conflicts.

It is different from https://github.com/ruby/ruby/commit/79eaaf2d0b641710613f16525e4b4c439dfe854e.

I don't understand which upstream commit is used for the patch, and I don't understand why the https://github.com/ruby/ruby/commit/2c190863239bee3f54cfb74b16bb6ea4cae6ed20 above on the comment is related to the Patch24, and on the comment.

If you look at the upstream PR, it actually removes the #if GC_CAN_COMPILE_COMPACTION
however, we retain it. To reflect all the sources for the patch as a whole (and cut down on confusion if one were to examine where is the source for the backport) I referenced the commit that readded the conditions as well as the PR.

I also see the ruby-3.2.0-detect_compaction_support_during_runtime.patch doesn't have git meta data. It's better to have it possible.

I presume you mean the output from e.g. git show command. As stated above, the reason is manual patch application essentially resulting in a squash of the commits. If we would be to add that, it would result in even more manual edits of the patch, and I am not comfortable with that. I'd rather expand our downstream commit message to explain why the patch is the way it is with relevant references.

I've checked the patch and built it in my COPR:

https://copr.fedorainfracloud.org/coprs/build/4548202

Thanks!

The test failure on x86_64 seems from related tests :/ but as the Fedora CI's test failed on the OpenSSL gem's test case I'd say it is not related to this change. (I'll try a copr build to check how it looks without LTO enabled.)

I don't understand the meaning of your statement. Could you explain in what way does the order matter?

That means this PR, the last line on the comment below is https://bugs.ruby-lang.org/issues/18829.

+# Define the GC compaction support macro at run time.
+# https://github.com/ruby/ruby/pull/6019
+# https://github.com/ruby/ruby/commit/2c190863239bee3f54cfb74b16bb6ea4cae6ed20
+# https://bugs.ruby-lang.org/issues/18829
+Patch24: ruby-3.2.0-detect_compaction_support_during_runtime.patch

But in the other parts, order of the sorted line, the https://bugs.ruby-lang.org/issues/18373 then https://github.com/ruby/ruby/pull/5774

# Workaround gem binary extensions build and installation issues.
# https://bugs.ruby-lang.org/issues/18373
# https://github.com/ruby/ruby/pull/5774
Patch21: ruby-3.2.0-Build-extension-libraries-in-bundled-gems.patch

I suggested something like this below.

+# Define the GC compaction support macro at run time.
+# https://bugs.ruby-lang.org/issues/18829
+# https://github.com/ruby/ruby/something ...
+Patch24: ruby-3.2.0-detect_compaction_support_during_runtime.patch

Manual backport.

OK. So, did you create manually the patch based on the 2 commits below? Sorry I haven't check it yet. I hope you explain the context in the commit message.
https://github.com/ruby/ruby/commit/79eaaf2d0b641710613f16525e4b4c439dfe854e
https://github.com/ruby/ruby/commit/2c190863239bee3f54cfb74b16bb6ea4cae6ed20

Or based on only one commit: [0] https://github.com/ruby/ruby/commit/0c36ba53192c5a0d245c9b626e4346a32d7d144e written in the commit message?

I suggested something like this below.

Yes, I agree. It is better to be consistent.

OK. So, did you create manually the patch based on the 2 commits below? Sorry I haven't check it > yet. I hope you explain the context in the commit message.
https://github.com/ruby/ruby/commit/79eaaf2d0b641710613f16525e4b4c439dfe854e
https://github.com/ruby/ruby/commit/2c190863239bee3f54cfb74b16bb6ea4cae6ed20

Or based on only one commit: [0] https://github.com/ruby/ruby/commit/0c36ba53192c5a0d245c9b626e4346a32d7d144e written in the commit message?

Ok, I see the commit message is not as good as I thought, as you and Pavel asked about this commit in about the same way. The message is copied from https://github.com/ruby/ruby/pull/6019#issue-1271302828 as it seemed good enough, which is also where the commit hash in the commit message comes from.

More to how it was applied: first apply the rb_f_notimplement patch I have backported on git sources (namely Patch22), commit it (to not have rogue changes in git diff), then apply the upstream patch manually, then git diff > gc.patch, nothing much out of ordinary IMO.

rebased onto 22fc4a3c1cc7bd12da3892da0313b9f264fbadbf

2 years ago

I enhanced the commit message and switched the link order.

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci

Thanks. Let me review it.

More to how it was applied: first apply the rb_f_notimplement patch I have backported on git sources (namely Patch22), commit it (to not have rogue changes in git diff), then apply the upstream patch manually, then git diff > gc.patch, nothing much out of ordinary IMO.

There is nothing particularly wrong with this workflow, but I'd always suggest to use:

$ git commit
$ git format-patch -1

This way, the patch looks as a regular git patch and might include additional details in comment, which is always :heavy_plus_sign:

BTW, I think most of the commit message of this PR should be actually moved into the commit message of the ruby-3.2.0-detect_compaction_support_during_runtime.patch.

This is a good practice to consider first when creating a patch. Because when i create a patch like this, we can apply a patch to a commit by git am or git apply in my memory.

$ git format-patch -1

BTW, I think most of the commit message of this PR should be actually moved into the commit message of the ruby-3.2.0-detect_compaction_support_during_runtime.patch.

I can agree on it. For especially a patch we create manually, maybe we want to manage it more carefully.

@jackrop just note to create a patch next time. When I tried to apply your previous patch on the Ruby 3.1.2. I wanted to apply it by git am, but seeing the patch, some of the git commit meta data is missing. So, the git am failed. Then I did patch -p1 < instead of that. It's more convenient if we can execute by git am or (git apply).

The steps what I did.

$ git checkout v3_1_2
$ git checkout -b wip/detect-compaction-runtime

The git am exits with error.

$ git am -3 < ~/fed/ruby/ruby-3.2.0-define-unsupported-gc-compaction-methods-as-rb_f_notimplement.patch
Applying: commit 6d1ca6737f31b2e24664a093f1827dd74a121a9f
fatal: empty ident name (for <>) not allowed

Reset the commit.

$ git am --abort
$ git reset --hard HEAD^

Did the patch -p1 instead of that.

$ patch -p1 < ~/fed/ruby/ruby-3.2.0-define-unsupported-gc-compaction-methods-as-rb_f_notimplement.patch

$ git add gc.c gc.rb test/ruby/test_gc_compact.rb
$ git commit

I created a patch by myself to verify your patch. Here is the patch. You can download.

https://jaruga.fedorapeople.org/issues/202206_detect-compaction-runtime/0001-Define-the-GC-compaction-support-during-run-time.patch

$ wget https://jaruga.fedorapeople.org/issues/202206_detect-compaction-runtime/0001-Define-the-GC-compaction-support-during-run-time.patch

Here is the branch I applied your previous patch ruby-3.2.0-define-unsupported-gc-compaction-methods-as-rb_f_notimplement.patch and a patch I created by myself.
https://github.com/junaruga/ruby/commits/wip/detect-compaction-runtime

On the branch with my patch, the make fails with the upstream source code. However I want to confirm the difference between your and my patches first.

Here is the diff file between your and my patches.
https://jaruga.fedorapeople.org/issues/202206_detect-compaction-runtime/diff.txt

$ diff ~/fed/ruby/ruby-3.2.0-detect_compaction_support_during_runtime.patch ~/git/ruby/ruby/0001-Define-the-GC-compaction-support-during-run-time.patch

Let me explain one by one. First please check my patch's meta data. It is a summary and how to create the patch.

The patch is essentially to apply a difference squashed from the 3 commits below on the master branch. I call the squashed difference "original difference" below.
https://github.com/ruby/ruby/commit/52d42e702375446746164a0251e1a10bce813b78
https://github.com/ruby/ruby/commit/79eaaf2d0b641710613f16525e4b4c439dfe854e
https://github.com/ruby/ruby/commit/2c190863239bee3f54cfb74b16bb6ea4cae6ed20

Here I think to keep the comment that exists on the original difference.

10c117
< +#if defined(__wasi__)
---
> +#if defined(__wasi__) /* WebAssembly doesn't support signals */
22c129
< +# define GC_COMPACTION_SUPPORTED (GC_CAN_COMPILE_COMPACTION && USE_MMAP_ALIGNED_ALLOC)
---
> +# define GC_COMPACTION_SUPPORTED (GC_CAN_COMPILE_COMPACTION && HEAP_PAGE_ALLOC_USE_MMAP)

I understand the HEAP_PAGE_ALLOC_USE_MMAP is not declared on the Ruby 3.1.2. So, my patch using the HEAP_PAGE_ALLOC_USE_MMAP is wrong. It causes a compile error. However why did you use the USE_MMAP_ALIGNED_ALLOC instead of the HEAP_PAGE_ALLOC_USE_MMAP?
https://github.com/ruby/ruby/commit/ea9c09a92c770e9e3cb0f5ceafd42c8407836f7e

97c204,206
< @@ -10816,6 +10828,7 @@ gc_set_auto_compact(VALUE _, VALUE v)
---
> @@ -10814,8 +10826,7 @@ gc_disable(rb_execution_context_t *ec, VALUE _)
>  static VALUE
>  gc_set_auto_compact(VALUE _, VALUE v)

I am not sure why the difference is here.

99,100c208,209
<      /* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
<       * the read barrier, so we must disable automatic compaction. */
---
> -    /* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
> -     * the read barrier, so we must disable automatic compaction. */

I think you keep the comment lines intentionally. But I like to remove it, because the difference is in the original difference.

110d218
< +

??

123a232
> +
129,130c238,239
< +        rb_define_singleton_method(rb_mGC, "verify_compaction_references", gc_verify_compaction_references, -1);
< +    } else {
---
> +    }
> +    else {

I don't understand why you added the verify_compaction_references line above. And the brackets } else { is not in the original patch. So, I think my else style is right in this case.

145c254
< +        OPT(GC_COMPACTION_SUPPORTED);
---
> + OPT(GC_COMPACTION_SUPPORTED);

Seeing your patch, you added the OPT(GC_COMPACTION_SUPPORTED); with space indent. But In the original patch is it is one tab indent. I think my patch is right.

148a258,260
> -- 
> 2.36.1
> 

This line in my patch is an output of the git format-patch -1. I want to keep the footer meta data, as we can use the git am for the patch.

One more thing, just in case, later I want to check how the methods in gc.c below are tested in the unit tests.

    if (GC_COMPACTION_SUPPORTED) {
        rb_define_singleton_method(rb_mGC, "compact", gc_compact, 0);
        rb_define_singleton_method(rb_mGC, "auto_compact", gc_get_auto_compact, 0);
        rb_define_singleton_method(rb_mGC, "auto_compact=", gc_set_auto_compact, 1);
        rb_define_singleton_method(rb_mGC, "latest_compact_info", gc_compact_stats, 0);
    }
    else {
        rb_define_singleton_method(rb_mGC, "compact", rb_f_notimplement, 0);
        rb_define_singleton_method(rb_mGC, "auto_compact", rb_f_notimplement, 0);
        rb_define_singleton_method(rb_mGC, "auto_compact=", rb_f_notimplement, 1);
        rb_define_singleton_method(rb_mGC, "latest_compact_info", rb_f_notimplement, 0);
        /* When !GC_COMPACTION_SUPPORTED, this method is not defined in gc.rb */
        rb_define_singleton_method(rb_mGC, "verify_compaction_references", rb_f_notimplement, -1);
    }

@jackorp FYI: Once more the COPR build succeeds on F36, but failed on Rawhide:
https://download.copr.fedorainfracloud.org/results/pvalena/ruby/fedora-rawhide-x86_64/04551757-ruby/builder-live.log.gz

Without a proper core dump (or at least ruby's SIGSEGV print) I cannot say if this patch is the cause. Right now I can only blame the (currently unknown, but probably related to Fedora build environment) cause that is causing random failures throughout the Ruby test suite as I made some C9S scratch builds with the patches and those are more or less stable in passing the full test suite.

ad all $ git format-patch I was unaware of that as a valid option previously. I can make proper use of that from now on.

I created a patch by myself to verify your patch. Here is the patch. You can download.

Thanks!

I call the squashed difference "original difference" below.

Correct

Here I think to keep the comment that exists on the original difference.

OK.

I understand the HEAP_PAGE_ALLOC_USE_MMAP is not declared on the Ruby 3.1.2. So, my patch using the HEAP_PAGE_ALLOC_USE_MMAP is wrong. It causes a compile error. However why did you use the USE_MMAP_ALIGNED_ALLOC instead of the HEAP_PAGE_ALLOC_USE_MMAP?

Essentially it is the same variable, there was a rename https://github.com/ruby/ruby/commit/fe21b7794af0cdb7ebd502e2c0da38c68fd89839 . The HEAP_PAGE_ALLOC_USE_MMAP does not exist in Ruby 3.1, and it is basically the same as USE_MMAP_ALIGNED_ALLOC.

I am not sure why the difference is here.

Me neither. Not really sure, looks the same to me in the file gc.c.

I think you keep the comment lines intentionally. But I like to remove it, because the difference is in the original difference.

I am not sure what you mean by this. I'd like to keep the comment, personally.
Found where they are, yes, a mistake on my part.

I don't understand why you added the verify_compaction_references line above.

Ruby devel branch vs 3.1.2 (what we have right now) difference in short. We unimplemented the verify_compaction_references from gc.rb, upstream readded it a few commits later... https://github.com/ruby/ruby/commit/b96a3a6fd2093e1dbea5491c002da515652dd347 ,
so we have to tell the Ruby interpreter in some way that that method exists, that is the meaning of that extra line.

And the brackets } else { is not in the original patch. So, I think my else style is right in this case.

2 syntax options that are semantically equal. Manually backporting it, I used the style I am used to (IOW one that I use automatically without thinking).

Seeing your patch, you added the OPT(GC_COMPACTION_SUPPORTED); with space indent. But In the original patch is it is one tab indent. I think my patch is right.

That is possible. I'll take a look.

One more thing, just in case, later I want to check how the methods in gc.c below are tested in the unit tests.

  1. assert_not_implemented (when the methods should be unimplemented because Ruby was compiled that way): https://src.fedoraproject.org/rpms/ruby/blob/rawhide/f/ruby-3.2.0-define-unsupported-gc-compaction-methods-as-rb_f_notimplement.patch#_278

  2. otherwise the file does OK job at testing compaction: https://github.com/ruby/ruby/blob/ruby_3_1/test/ruby/test_gc_compact.rb

If there would be a major problem, it would fail either on the assert_not_implemented if they are implemented when they should not be or it would fail on compaction methods themselves when they are implemented but are not working properly.


I think I addressed all the comments via text, if I missed something, please let me know.

rebased onto 219d374d8e049d4aae1b541a4cb846bc05a4a683

2 years ago

I have addressed the comments in the latest rebase.

Build succeeded.

Thanks. Let me review it again.

Sorry this was originally my typo. Not "the squashed on commit" but "the squashed one commit".

Just for your information. I am using the setting below on my .vimrc to visualize tab on VIM.

" Display special sign
set list
set listchars=tab:>-,trail:-,nbsp:%,extends:>,precedes:<

rebased onto c5ad55c50438712830cd0fc2237cddde7b8aac0d

2 years ago

Sorry this was originally my typo. Not "the squashed on commit" but "the squashed one commit".
Fixed in newest rebase.

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci

Sorry I am still in review. Please don't merge this PR yet until I will say OK.

Essentially it is the same variable, there was a rename https://github.com/ruby/ruby/commit/fe21b7794af0cdb7ebd502e2c0da38c68fd89839 . The HEAP_PAGE_ALLOC_USE_MMAP does not exist in Ruby 3.1, and it is basically the same as USE_MMAP_ALIGNED_ALLOC.

OK. Thanks for the explanation.

Ruby devel branch vs 3.1.2 (what we have right now) difference in short. We unimplemented the verify_compaction_references from gc.rb, upstream readded it a few commits later... https://github.com/ruby/ruby/commit/b96a3a6fd2093e1dbea5491c002da515652dd347 ,
so we have to tell the Ruby interpreter in some way that that method exists, that is the meaning of that extra line.

I see. Seeing other parts in the https://github.com/ruby/ruby/commit/b96a3a6fd2093e1dbea5491c002da515652dd347 , I am trying to check if other parts should be added or removed.

For example PT(GC_COMPACTION_SUPPORTED); in gc.c and a change at test/ruby/test_gc_compact.rb. Sorry for my delayed review and reresponse.

One more thing, just in case, later I want to check how the methods in gc.c below are tested in the unit tests.

For your reply on my comment above, I haven't check it yet.

For example PT(GC_COMPACTION_SUPPORTED); in gc.c and a change at test/ruby/test_gc_compact.rb. Sorry for my delayed review and reresponse.

OPT(GC_COMPACTION_SUPPORTED); line can IMO stay. AFAICT it just exposes the macro value from C to Ruby.

test/ruby/test_gc_compact.rb, is more or less optional for our use case and platforms we support. Testing current state locally in IRB:

irb(main):004:0> (GC::INTERNAL_CONSTANTS[:HEAP_PAGE_SIZE]  % Etc.sysconf(Etc::SC_PAGE_SIZE)) == 0
=> true

If we would be on e.g. ppc64le where Etc.sysconf(Etc::SC_PAGE_SIZE) should evaluate to 64 KiB (65536):

irb(main):005:0> (GC::INTERNAL_CONSTANTS[:HEAP_PAGE_SIZE]  % 65536) == 0
=> false

Note that this is similar to the C behavior of USE_MMAP_ALIGNED_ALLOC (~= HEAP_PAGE_ALLOC_USE_MMAP) from C counterparts where the macro is evaluated at compile time: https://github.com/ruby/ruby/blob/master/gc.c#L897 and even at runtime: https://github.com/ruby/ruby/blob/master/gc.c#L3706 .

All right, now I checked everything I can do.

If there would be a major problem, it would fail either on the assert_not_implemented if they are implemented when they should not be or it would fail on compaction methods themselves when they are implemented but are not working properly.

OK. Thanks for the explanation about where the unit tests test the GC methods.

One thing. I want to see the comment below is added in the patch after the section "== How to create this patch ==" or in the session. The 2 points were important for me to understand how you created the patch. We want to remember those points if we may need to understand or debug the patch in the future. I hope you would check if my comment below in the patch is correct or not. This is my understanding for the points. Other parts look ok. After rebasing the patch again, let me know. Thanks.

== Notes for the patch ==

```
+# define GC_COMPACTION_SUPPORTED (GC_CAN_COMPILE_COMPACTION && USE_MMAP_ALIGNED_ALLOC)
```

We use the USE_MMAP_ALIGNED_ALLOC instead of HEAP_PAGE_ALLOC_USE_MMAP on the
line above. Because while the Ruby on the master branch replaced the
USE_MMAP_ALIGNED_ALLOC with HEAP_PAGE_ALLOC_USE_MMAP, Ruby 3.1.2 doesn't.
See <https://github.com/ruby/ruby/commit/fe21b7794af0cdb7ebd502e2c0da38c68fd89839>.


```      
+        rb_define_singleton_method(rb_mGC, "verify_compaction_references", gc_verify_compaction_references, -1);
```

We added the line in the case that GC_COMPACTION_SUPPORTED is true. Because
while the Ruby on the master branch defines the GC.verify_compaction_references in
the gc.rb in the case that GC_COMPACTION_SUPPORTED is true, Ruby 3.1.2 doesn't
define it in the gc.rb.
See <https://github.com/ruby/ruby/commit/b96a3a6fd2093e1dbea5491c002da515652dd347>.
We also applied some changes on the commit.

The text is LGTM. Thanks.

One small nit:

We also applied some changes on the commit.

What do you mean here? If you mean the commit https://github.com/ruby/ruby/commit/b96a3a6fd2093e1dbea5491c002da515652dd347 , we did not apply changes on that, however, there are a few lines we applied (took) that originate from there.

rebased onto ca94aff

2 years ago

Rebased. I also added a note on the OPT(GC_COMPACTION_SUPPORTED).

What do you mean here? If you mean the commit https://github.com/ruby/ruby/commit/b96a3a6fd2093e1dbea5491c002da515652dd347 , we did not apply changes on that, however, there are a few lines we applied (took) that originate from there.

Thanks for checking. Yes, I meant the commit b96a3a6fd2093e1dbea5491c002da515652dd347.

For detail, I meant the 2 lines below are included in the patch.

Especially, the second line OPT(GC_COMPACTION_SUPPORTED) is not merged when just merging the 3 commits below into Ruby 3.1.2. So, people may wonder why the OPT(GC_COMPACTION_SUPPORTED) is included in the patch.

The patch is essentially to apply a difference squashed from the 3 commits below on the master branch. I call the squashed difference "original difference" below.
https://github.com/ruby/ruby/commit/52d42e702375446746164a0251e1a10bce813b78
https://github.com/ruby/ruby/commit/79eaaf2d0b641710613f16525e4b4c439dfe854e
https://github.com/ruby/ruby/commit/2c190863239bee3f54cfb74b16bb6ea4cae6ed20

Let me check your rebase.

Let me check your rebase.

I checked your rebase (the rebased commit message). Now I APPROVED this PR. Thanks. Feel free to merge and build it.

Build failed. More information on how to proceed and troubleshoot errors available at https://fedoraproject.org/wiki/Zuul-based-ci

Pull-Request has been merged by jackorp

2 years ago