[#112638] [Ruby master Bug#19470] Frequent small range-reads from and then writes to a large array are very slow — "giner (Stanislav German-Evtushenko) via ruby-core" <ruby-core@...>

Issue #19470 has been reported by giner (Stanislav German-Evtushenko).

8 messages 2023/03/01

[#112664] [Ruby master Bug#19473] can't be called from trap context (ThreadError) is too limiting — "Eregon (Benoit Daloze) via ruby-core" <ruby-core@...>

Issue #19473 has been reported by Eregon (Benoit Daloze).

28 messages 2023/03/02

[#112681] [Ruby master Misc#19475] Propose Matthew Valentine-House (@eightbitraptor) as a core committer — "k0kubun (Takashi Kokubun) via ruby-core" <ruby-core@...>

SXNzdWUgIzE5NDc1IGhhcyBiZWVuIHJlcG9ydGVkIGJ5IGswa3VidW4gKFRha2FzaGkgS29rdWJ1

11 messages 2023/03/03

[#112744] [Ruby master Bug#19485] Unexpected behavior in squiggly heredocs — "jemmai (Jemma Issroff) via ruby-core" <ruby-core@...>

Issue #19485 has been reported by jemmai (Jemma Issroff).

9 messages 2023/03/08

[#112746] [Ruby master Bug#19518] Recent Source Releases Do Not Compile on CentOS 7 Due to configure Script Error Generated By autoconf >= 2.70 — "eviljoel (evil joel) via ruby-core" <ruby-core@...>

Issue #19518 has been reported by eviljoel (evil joel).

7 messages 2023/03/08

[#112770] [Ruby master Feature#19520] Support for `Module.new(name)` and `Class.new(superclass, name)`. — "ioquatix (Samuel Williams) via ruby-core" <ruby-core@...>

Issue #19520 has been reported by ioquatix (Samuel Williams).

42 messages 2023/03/09

[#112773] [Ruby master Feature#19521] Support for `Module#name=` and `Class#name=`. — "ioquatix (Samuel Williams) via ruby-core" <ruby-core@...>

Issue #19521 has been reported by ioquatix (Samuel Williams).

31 messages 2023/03/09

[#112818] [Ruby master Misc#19525] DevMeeting-2023-04-13 — "mame (Yusuke Endoh) via ruby-core" <ruby-core@...>

Issue #19525 has been reported by mame (Yusuke Endoh).

8 messages 2023/03/10

[#112871] [Ruby master Bug#19529] [BUG] ObjectSpace::WeakMap can segfault after compaction — "byroot (Jean Boussier) via ruby-core" <ruby-core@...>

Issue #19529 has been reported by byroot (Jean Boussier).

12 messages 2023/03/14

[#112926] [Ruby master Misc#19535] Instance variables order is unpredictable on objects with `OBJ_TOO_COMPLEX_SHAPE_ID` — "byroot (Jean Boussier) via ruby-core" <ruby-core@...>

Issue #19535 has been reported by byroot (Jean Boussier).

8 messages 2023/03/17

[#112933] [Ruby master Feature#19538] Performance warnings — "byroot (Jean Boussier) via ruby-core" <ruby-core@...>

Issue #19538 has been reported by byroot (Jean Boussier).

11 messages 2023/03/17

[#112944] [Ruby master Feature#19541] Proposal: Generate frame unwinding info for YJIT code — "kjtsanaktsidis (KJ Tsanaktsidis) via ruby-core" <ruby-core@...>

SXNzdWUgIzE5NTQxIGhhcyBiZWVuIHJlcG9ydGVkIGJ5IGtqdHNhbmFrdHNpZGlzIChLSiBUc2Fu

13 messages 2023/03/19

[#113033] [Ruby master Feature#19555] Allow passing default options to `Data.define` — "p8 (Petrik de Heus) via ruby-core" <ruby-core@...>

Issue #19555 has been reported by p8 (Petrik de Heus).

7 messages 2023/03/28

[#113045] [Ruby master Feature#19559] Introduce `Symbol#+@` and `Symbol#-@`, and eventually replace boolean arguments with symbols — "sawa (Tsuyoshi Sawada) via ruby-core" <ruby-core@...>

Issue #19559 has been reported by sawa (Tsuyoshi Sawada).

20 messages 2023/03/30

[#113059] [Ruby master Bug#19563] Ripper.tokenize(code).join != code when heredoc and multiline %w[] literal is on the same line — "tompng (tomoya ishida) via ruby-core" <ruby-core@...>

Issue #19563 has been reported by tompng (tomoya ishida).

6 messages 2023/03/31

[ruby-core:112857] [Ruby master Feature#19406] Allow declarative reference definition for rb_typed_data_struct

From: "ko1 (Koichi Sasada) via ruby-core" <ruby-core@...>
Date: 2023-03-12 15:17:14 UTC
List: ruby-core #112857
Issue #19406 has been updated by ko1 (Koichi Sasada).


eightbitraptor (Matthew Valentine-House) wrote in #note-4:
> > * (matz) can we have better macro to define the memory layout (`enumerator_refs`)?
> 
> I tried this in a previous iteration (in fact I accidentally left a reference to the `RUBY_REFERENCE_LIST` macro in the rdoc). The problem is that we require C++98 support for C extensions, so I am unable to use `__VA_ARGS__` to declare arbitrary size reference lists. 
> 
> I know there are ways to work around this in the pre-processor, but this would require us to have an upper limit on the number of references. Whatever limit we choose could end up being a problem for C extensions...

On the dev-meeting, there were some comments about that:

(1) interpreter core doesn't need to care about C++ compilers.
(2) should we care about old C++ compilers for newly created C-extensions?

anyway, name better macro names can improve the issue.


----------------------------------------
Feature #19406: Allow declarative reference definition for rb_typed_data_struct
https://bugs.ruby-lang.org/issues/19406#change-102368

* Author: eightbitraptor (Matthew Valentine-House)
* Status: Open
* Priority: Normal
----------------------------------------
[Github PR 7153](https://github.com/ruby/ruby/pull/7153)

## Summary

This PR proposes an additional API for C extension authors to define wrapped
struct members that point to Ruby objects, when the struct being wrapped
contains only members with primitive types (ie. no arrays or unions). The new
interface passes an offset from the top of the data structure, rather than the
reference `VALUE` itself, allowing the GC to manipulate both the reference edge
(the address holding the pointer), as well as the underlying object.

This allows Ruby's GC to handle marking, object movement and reference updating
independently without calling back into user supplied code.

## Implementation

When a wrapped struct contains a simple list of members (such as the 
`struct enumerator` in `enumerator.c`). We can declare all of the struct members that
may point to valid Ruby objects as `RUBY_REF_EDGE` in a static array.

If we choose to do this, then we can mark the corresponding `rb_data_type_t` as
`RUBY_TYPED_DECL_MARKING` and pass a pointer to the references array in the
`data` field.

To avoid having to also find space in the `rb_data_type_t` to define a length for
the references list, I've chosen to require list termination
with `RUBY_REF_END` - defined as `UINTPTR_MAX`. My assumption is that no
single wrapped struct will ever be large enough that `UINTPTR_MAX` is actually a
valid reference.

We don't have to then define `dmark` or `dcompact` callback functions. Marking,
object movement, and reference updating will be handled for us by the GC.

```C
struct enumerator {
    VALUE obj;
    ID    meth;
    VALUE args;
    VALUE fib;
    VALUE dst;
    VALUE lookahead;
    VALUE feedvalue;
    VALUE stop_exc;
    VALUE size;
    VALUE procs;
    rb_enumerator_size_func *size_fn;
    int kw_splat;
};

static const size_t enumerator_refs[] = {
    RUBY_REF_EDGE(enumerator, obj),
    RUBY_REF_EDGE(enumerator, args),
    RUBY_REF_EDGE(enumerator, fib),
    RUBY_REF_EDGE(enumerator, dst),
    RUBY_REF_EDGE(enumerator, lookahead),
    RUBY_REF_EDGE(enumerator, feedvalue),
    RUBY_REF_EDGE(enumerator, stop_exc),
    RUBY_REF_EDGE(enumerator, size),
    RUBY_REF_EDGE(enumerator, procs),
    RUBY_REF_END
};

static const rb_data_type_t enumerator_data_type = {
    "enumerator",
    {
        NULL,
        enumerator_free,
        enumerator_memsize,
        NULL,
    },
    0, (void *)enumerator_refs, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_DECL_MARKING
};
```

### Benchmarking

Benchmarking shows that this reference declaration style does not degrade
performance when compared to the callback style.

To benchmark this we created a C extension that initialized a struct with 20
`VALUE` members, all set to point to Ruby strings. We wrapped each struct using
`TypedData_Make_Struct` in an object. One object was configured with callback
functions and one was configured with declarative references.

In separate scripts we then created 500,000 of these objects, added them to a
list, so they would be marked and not swept and used
`GC.verify_compaction_references` to make sure everything that could move, did.

Finally we created a wrapper script that used seperate processes to run each GC
type (to ensure that the GC's were completely independent), ran each benchmark
50 times, and collected the results of `GC.stat[:time]`.

We did this on an M1 Pro MacBook (aarch64), and a Ryzen 3600 We then plotted the
results:

![chart showing GC time between callback and declarative marking on arm64 and
x86_64](https://user-images.githubusercontent.com/31869/216573409-ddafa3bd-9af7-4b60-ba61-355da7e71910.png)

As we can see from this, there has been no real impact to GC performance in our
benchmarks.

Benchmark code and harnesses is [available in this Github
repo](https://github.com/eightbitraptor/test_decl_marking)

## Justification

Requiring extension authors to implement seperate `dmark` and `dcompact`
callbacks can be error-prone, and pushes GC responsibilities from the GC into
user supplied code. This can be a source of bugs arising from the `dmark` and
`dcompact` functions being implemented incorrectly, or becoming out of sync with each other.

There has already been work done by @Peterzhu2118 [to try and unify these
callbacks](https://github.com/ruby/ruby/pull/7140), so that authors can define a
single function, that will be used for both marking and compacting, removing the
risk of these callbacks becoming out of sync.

This proposal works alongside Peter's earlier work to eliminate the
callbacks entirely for the "simple reference" case.

This means that extension authors with simple structs to wrap can declare which
of their struct members point to Ruby objects to get GC marking and compaction
support. And extension authors with more complex requirements will only have to
implement a single function, using Peter's work.

In addition to this, passing the GC the address of a reference rather than the
reference itself (edge based, rather than object based enqueing), allows the GC
itself to have more control over how it manipulates that reference.

This means that when considering alternative GC implementations for Ruby (such
as our [ongoing work integrating MMTk into
Ruby](https://github.com/mmtk/mmtk-ruby)[^1]), We don't need to call from Ruby
into library code, and then back into Ruby code as often; which can increase
performance, and allow more complex algorithms to be implemented.

[^1]: [MMtk](https://www.mmtk.io/) is the Memory Management Toolkit. A framework
    for implementing automatic memory management strategies

## Trade-offs

This PR provides another method for defining references in C extensions, in
addition to the callback based approach, effectively widening the extension API.
Extension authors will now need to choose whether to use the declarative
approach, or a callback based approach depending on their use case. This is more
complex for extension authors.

However because the callback's do still exist, this does mean that extension
authors can migrate their own code to this new, faster approach at their
leisure.

## Further work

As part of this work we inspected all uses of `rb_data_type_t` in the Ruby
source code and of 134 separete instances, 60 wrapped structs that contained
`VALUE` members that could point to Ruby objects. Out of these 27 were "simple"
structs that would benefit from this approach, 28 contained complex references
(unions, loops etc) that won't work with this approach, and 5 were situations
that were unsure, that we believe we could make work given some slight
refactors.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

In This Thread

Prev Next