mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 21:49:06 +02:00
Destroyed RGenGC (markdown)
parent
bfc79dba5d
commit
95d607acad
1 changed files with 0 additions and 119 deletions
119
RGenGC.md
119
RGenGC.md
|
@ -1,119 +0,0 @@
|
||||||
# RGenGC
|
|
||||||
|
|
||||||
RGenGC is generational garbage collection algorithm arranged for MRI/CRuby introduced from Ruby 2.1.
|
|
||||||
RGenGC (mostly) keeps compatibility.
|
|
||||||
|
|
||||||
# For extension writes
|
|
||||||
|
|
||||||
Generally, the use of the technique called write barriers is required in
|
|
||||||
extension libraries for generational GC
|
|
||||||
(http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29).
|
|
||||||
RGenGC works fine without write barriers in extension libraries.
|
|
||||||
|
|
||||||
If your library adheres to the following tips, performance can
|
|
||||||
be further improved. Especially, the "Don't touch pointers directly" section is
|
|
||||||
important.
|
|
||||||
|
|
||||||
## Incompatibility
|
|
||||||
|
|
||||||
You can't write RBASIC(obj)->klass field directly because it is const
|
|
||||||
value now.
|
|
||||||
|
|
||||||
Basically you should not write this field because MRI expects it to be
|
|
||||||
an immutable field, but if you want to do it in your extension you can
|
|
||||||
use the following functions:
|
|
||||||
|
|
||||||
```
|
|
||||||
VALUE rb_obj_hide(VALUE obj) ::
|
|
||||||
|
|
||||||
Clear RBasic::klass field. The object will be an internal object.
|
|
||||||
ObjectSpace::each_object can't find this object.
|
|
||||||
|
|
||||||
VALUE rb_obj_reveal(VALUE obj, VALUE klass) ::
|
|
||||||
|
|
||||||
Reset RBasic::klass to be klass.
|
|
||||||
We expect the `klass' is hidden class by rb_obj_hide().
|
|
||||||
```
|
|
||||||
|
|
||||||
## Write barriers
|
|
||||||
|
|
||||||
RGenGC doesn't require write barriers to support generational GC.
|
|
||||||
However, caring about write barrier can improve the performance of
|
|
||||||
RGenGC. Please check the following tips.
|
|
||||||
|
|
||||||
### Don't touch pointers directly
|
|
||||||
|
|
||||||
In MRI (include/ruby/ruby.h), some macros to acquire pointers to the
|
|
||||||
internal data structures are supported such as RARRAY_PTR(),
|
|
||||||
RSTRUCT_PTR() and so on.
|
|
||||||
|
|
||||||
DO NOT USE THESE MACROS and instead use the corresponding C-APIs such as
|
|
||||||
rb_ary_aref(), rb_ary_store() and so on.
|
|
||||||
|
|
||||||
### Consider whether to insert write barriers
|
|
||||||
|
|
||||||
You don't need to care about write barriers if you only use built-in
|
|
||||||
types.
|
|
||||||
|
|
||||||
If you support T_DATA objects, you may consider using write barriers.
|
|
||||||
|
|
||||||
Inserting write barriers into T_DATA objects only works with the
|
|
||||||
following type objects: (a) long-lived objects, (b) when a huge number
|
|
||||||
of objects are generated and (c) container-type objects that have
|
|
||||||
references to other objects. If your extension provides such a type of
|
|
||||||
T_DATA objects, consider inserting write barriers.
|
|
||||||
|
|
||||||
* (a): short-lived objects don't become old generation objects.
|
|
||||||
* (b): only a few oldgen objects don't have performance impact.
|
|
||||||
* (c): only a few references don't have performance impact.
|
|
||||||
|
|
||||||
Inserting write barriers is a very difficult hack, it is easy to
|
|
||||||
introduce critical bugs. And inserting write barriers has several areas
|
|
||||||
of overhead. Basically we don't recommend you insert write barriers.
|
|
||||||
Please carefully consider the risks.
|
|
||||||
|
|
||||||
### Combine with built-in types
|
|
||||||
|
|
||||||
Please consider utilizing built-in types. Most built-in types support
|
|
||||||
write barrier, so you can use them to avoid manually inserting write
|
|
||||||
barriers.
|
|
||||||
|
|
||||||
For example, if your T_DATA has references to other objects, then you
|
|
||||||
can move these references to Array. A T_DATA object only has a reference
|
|
||||||
to an array object. Or you can also use a Struct object to gather a
|
|
||||||
T_DATA object (without any references) and an that Array contains
|
|
||||||
references.
|
|
||||||
|
|
||||||
With use of such techniques, you don't need to insert write barriers
|
|
||||||
anymore.
|
|
||||||
|
|
||||||
### Insert write barriers
|
|
||||||
|
|
||||||
*AGAIN* Inserting write barriers is a very difficult hack, and it is
|
|
||||||
easy to introduce critical bugs. And inserting write barriers has
|
|
||||||
several areas of overhead. Basically we don't recommend you insert write
|
|
||||||
barriers. Please carefully consider the risks.
|
|
||||||
|
|
||||||
Before inserting write barriers, you need to know about RGenGC algorithm
|
|
||||||
(gc.c will help you). Macros and functions to insert write barriers are
|
|
||||||
available in in include/ruby/ruby.h. An example is available in iseq.c.
|
|
||||||
|
|
||||||
NOTE: The following core interfaces can be changed in the future. Please catch up if you want to insert WB into C-extensions correctly.
|
|
||||||
|
|
||||||
Write barrier macros:
|
|
||||||
|
|
||||||
```
|
|
||||||
RB_OBJ_WRITE(a, slot, b) ::
|
|
||||||
|
|
||||||
WB for new reference from `a' to `b'.
|
|
||||||
Write `b' into `*slot'. `slot' is a pointer in `a'.
|
|
||||||
|
|
||||||
RB_OBJ_WRITTEN(a, oldv, b)::
|
|
||||||
|
|
||||||
WB for new reference from `a' to `b'.
|
|
||||||
This doesn't write any values, but only a WB declaration.
|
|
||||||
`oldv' is replaced value with `b' (not used in current Ruby).
|
|
||||||
```
|
|
||||||
|
|
||||||
See source code carefully to insert write barriers.
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue