RGenGC » History » Version 5

Koichi Sasada, 12/24/2013 02:19 PM

1 1 Koichi Sasada
=begin
2 1 Koichi Sasada
= RGenGC
3 1 Koichi Sasada
4 2 Koichi Sasada
RGenGC is generational garbage collection algorithm arranged for MRI/CRuby introduced from Ruby 2.1.
5 2 Koichi Sasada
RGenGC (mostly) keeps compatibility.
6 1 Koichi Sasada
7 1 Koichi Sasada
= For extension writes
8 1 Koichi Sasada
9 2 Koichi Sasada
Generally, the use of the technique called write barriers is required in
10 2 Koichi Sasada
extension libraries for generational GC
11 2 Koichi Sasada
(http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29).
12 2 Koichi Sasada
RGenGC works fine without write barriers in extension libraries.
13 1 Koichi Sasada
14 2 Koichi Sasada
If your library adheres to the following tips, performance can
15 2 Koichi Sasada
be further improved. Especially, the "Don't touch pointers directly" section is
16 2 Koichi Sasada
important.
17 2 Koichi Sasada
18 2 Koichi Sasada
== Incompatibility
19 2 Koichi Sasada
20 2 Koichi Sasada
You can't write RBASIC(obj)->klass field directly because it is const
21 2 Koichi Sasada
value now.
22 2 Koichi Sasada
23 2 Koichi Sasada
Basically you should not write this field because MRI expects it to be
24 2 Koichi Sasada
an immutable field, but if you want to do it in your extension you can
25 2 Koichi Sasada
use the following functions:
26 2 Koichi Sasada
27 2 Koichi Sasada
VALUE rb_obj_hide(VALUE obj) ::
28 2 Koichi Sasada
29 2 Koichi Sasada
  Clear RBasic::klass field. The object will be an internal object.
30 2 Koichi Sasada
  ObjectSpace::each_object can't find this object.
31 2 Koichi Sasada
32 2 Koichi Sasada
VALUE rb_obj_reveal(VALUE obj, VALUE klass) ::
33 2 Koichi Sasada
34 2 Koichi Sasada
  Reset RBasic::klass to be klass.
35 2 Koichi Sasada
  We expect the `klass' is hidden class by rb_obj_hide().
36 2 Koichi Sasada
37 2 Koichi Sasada
== Write barriers
38 2 Koichi Sasada
39 2 Koichi Sasada
RGenGC doesn't require write barriers to support generational GC.
40 2 Koichi Sasada
However, caring about write barrier can improve the performance of
41 2 Koichi Sasada
RGenGC. Please check the following tips.
42 2 Koichi Sasada
43 2 Koichi Sasada
=== Don't touch pointers directly
44 2 Koichi Sasada
45 2 Koichi Sasada
In MRI (include/ruby/ruby.h), some macros to acquire pointers to the
46 2 Koichi Sasada
internal data structures are supported such as RARRAY_PTR(),
47 2 Koichi Sasada
RSTRUCT_PTR() and so on.
48 2 Koichi Sasada
49 2 Koichi Sasada
DO NOT USE THESE MACROS and instead use the corresponding C-APIs such as
50 2 Koichi Sasada
rb_ary_aref(), rb_ary_store() and so on.
51 2 Koichi Sasada
52 2 Koichi Sasada
=== Consider whether to insert write barriers
53 2 Koichi Sasada
54 2 Koichi Sasada
You don't need to care about write barriers if you only use built-in
55 2 Koichi Sasada
types.
56 2 Koichi Sasada
57 2 Koichi Sasada
If you support T_DATA objects, you may consider using write barriers.
58 2 Koichi Sasada
59 2 Koichi Sasada
Inserting write barriers into T_DATA objects only works with the
60 2 Koichi Sasada
following type objects: (a) long-lived objects, (b) when a huge number
61 2 Koichi Sasada
of objects are generated and (c) container-type objects that have
62 2 Koichi Sasada
references to other objects. If your extension provides such a type of
63 2 Koichi Sasada
T_DATA objects, consider inserting write barriers.
64 2 Koichi Sasada
65 2 Koichi Sasada
(a): short-lived objects don't become old generation objects.
66 2 Koichi Sasada
(b): only a few oldgen objects don't have performance impact.
67 2 Koichi Sasada
(c): only a few references don't have performance impact.
68 2 Koichi Sasada
69 2 Koichi Sasada
Inserting write barriers is a very difficult hack, it is easy to
70 2 Koichi Sasada
introduce critical bugs. And inserting write barriers has several areas
71 2 Koichi Sasada
of overhead. Basically we don't recommend you insert write barriers.
72 2 Koichi Sasada
Please carefully consider the risks.
73 2 Koichi Sasada
74 2 Koichi Sasada
=== Combine with built-in types
75 2 Koichi Sasada
76 2 Koichi Sasada
Please consider utilizing built-in types. Most built-in types support
77 2 Koichi Sasada
write barrier, so you can use them to avoid manually inserting write
78 2 Koichi Sasada
barriers.
79 2 Koichi Sasada
80 2 Koichi Sasada
For example, if your T_DATA has references to other objects, then you
81 2 Koichi Sasada
can move these references to Array. A T_DATA object only has a reference
82 2 Koichi Sasada
to an array object. Or you can also use a Struct object to gather a
83 2 Koichi Sasada
T_DATA object (without any references) and an that Array contains
84 2 Koichi Sasada
references.
85 2 Koichi Sasada
86 2 Koichi Sasada
With use of such techniques, you don't need to insert write barriers
87 2 Koichi Sasada
anymore.
88 2 Koichi Sasada
89 2 Koichi Sasada
=== Insert write barriers
90 2 Koichi Sasada
91 2 Koichi Sasada
[AGAIN] Inserting write barriers is a very difficult hack, and it is
92 2 Koichi Sasada
easy to introduce critical bugs. And inserting write barriers has
93 2 Koichi Sasada
several areas of overhead. Basically we don't recommend you insert write
94 2 Koichi Sasada
barriers. Please carefully consider the risks.
95 2 Koichi Sasada
96 2 Koichi Sasada
Before inserting write barriers, you need to know about RGenGC algorithm
97 2 Koichi Sasada
(gc.c will help you). Macros and functions to insert write barriers are
98 2 Koichi Sasada
available in in include/ruby/ruby.h. An example is available in iseq.c.
99 2 Koichi Sasada
100 4 Koichi Sasada
NOTE: The following core interfaces can be changed in the future. Please catch up if you want to insert WB into C-extensions correctly.
101 4 Koichi Sasada
102 3 Koichi Sasada
Write barrier macros:
103 1 Koichi Sasada
104 3 Koichi Sasada
RB_OBJ_WRITE(a, slot, b) ::
105 3 Koichi Sasada
106 3 Koichi Sasada
  WB for new reference from `a' to `b'.
107 3 Koichi Sasada
  Write `b' into `*slot'. `slot' is a pointer in `a'.
108 3 Koichi Sasada
109 3 Koichi Sasada
RB_OBJ_WRITTEN(a, oldv, b)::
110 3 Koichi Sasada
111 3 Koichi Sasada
  WB for new reference from `a' to `b'.
112 3 Koichi Sasada
  This doesn't write any values, but only a WB declaration.
113 3 Koichi Sasada
  `oldv' is replaced value with `b' (not used in current Ruby).
114 3 Koichi Sasada
115 5 Koichi Sasada
See source code carefully to insert write barriers.
116 5 Koichi Sasada
117 3 Koichi Sasada
... [TBD]
118 1 Koichi Sasada
119 1 Koichi Sasada
=end