nakayoshi_fork 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bbd5b16ca6ba975467e87a88a25fab44ff12cdf6
4
+ data.tar.gz: 56a78a2c19dc85a84cd21b3073a7d08e28907ee2
5
+ SHA512:
6
+ metadata.gz: a2ea7583d349bbaa7b7e2a647cbfe7fbef280acd7e6583c3f82bcd177df64867774863cc99477d84ead799e6466000f84d19f99dbb13d8422c1c86136ffdc76f
7
+ data.tar.gz: d5f598c8fd57e3af35505f51a9fe5fd4cd3ad7c9e9b4a753f1a613463323efeb1ebca57a2d78aff723476c35e7d28430ff701e8c237cd5ea0a692940ce03dfa9
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in nakayoshi_fork.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Koichi Sasada
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,312 @@
1
+ # NakayoshiFork
2
+
3
+ nakayoshi_fork gem solves CoW friendly problem on MRI 2.2 and later.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'nakayoshi_fork'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install nakayoshi_fork
20
+
21
+ ## Usage
22
+
23
+ You only need to `require "nakayoshi-fork"`.
24
+
25
+ If you want to disable nakayoshi-fork, then use `fork(nakayoshi: false)` or `fork(cow_friendly: false)`.
26
+
27
+ ## Mechanism
28
+
29
+ MRI 2.1 employs generational GC algorithms that separate YOUNG objects and OLD objects.
30
+ Young objects will be promoted to old objects when they survive 1 GC.
31
+ After surviving 1 GC, set OLD bit for each young objects. So that we can recognize the promoted objects are old objects.
32
+ MRI 2.1 uses bitmap for the old object bit and it is CoW friendly.
33
+
34
+ However, Ruby 2.2 employs an algorithm to promote young objects after 3 GCs.
35
+ To count GC surviving number, all of objects have *age* field per objects (2 bits field to count 0 to 3).
36
+ Created objects are age 0, and age 3 objects are promoted (old) objects.
37
+
38
+ Unfortunately, age fileds are embed to object header, so that when there are many young objects,
39
+ but promoted soon is problem because their object headers are written and mark as dirty page.
40
+ This is why MRI 2.2 has CoW friendly problem on fork.
41
+
42
+ nakayoshi_fork gem promotes most of young objects before fork by invoking GC some times.
43
+
44
+ ### Result:
45
+
46
+ The following results are tests using nakayoshi-fork on my environment (2GB 64bit CPU Ubuntu machine).
47
+
48
+ Test script is here:
49
+
50
+ ```ruby
51
+ # make 2**(n+1) ary
52
+ def make_obj n
53
+ if n > 0
54
+ [make_obj(n-1), make_obj(n-1)]
55
+ else
56
+ []
57
+ end
58
+ end
59
+
60
+ def object_count
61
+ b = GC.stat[:total_allocated_objects] || GC.stat[:total_allocated_object]
62
+ yield
63
+ a = GC.stat[:total_allocated_objects] || GC.stat[:total_allocated_object]
64
+ a - b
65
+ end
66
+
67
+ created = object_count{
68
+ $objs = make_obj(21) # 4M objects -> 4M * 40B = 160MB
69
+ }
70
+
71
+ puts "created #{created} objects, consumed: #{created * 40 / (1024 * 1024)} MB"
72
+
73
+ def mem_usage
74
+ _, total, used, free = `free -m -o | grep Mem`.split(/\s+/)
75
+ {total_mem: total, used_mem: used, free_mem: free}
76
+ end
77
+
78
+ # make 10 processes
79
+ 10.times{
80
+ fork{
81
+ puts 'before gc: ' + mem_usage.inspect
82
+ sleep 5
83
+ puts :GC
84
+ GC.start
85
+ sleep 5
86
+ puts 'after gc :' + mem_usage.inspect
87
+ sleep 5
88
+ }
89
+ }
90
+ 10.times{Process.wait}
91
+ puts 'after terminate all processes: ' + mem_usage.inspect
92
+ ```
93
+
94
+ Without nakayoshi-fork:
95
+
96
+ ```
97
+ ruby 2.0.0p402 (2014-02-11) [x86_64-linux]
98
+ created 4194305 objects, consumed: 160 MB
99
+ before gc: {:total_mem=>"2001", :used_mem=>"386", :free_mem=>"1615"}
100
+ before gc: {:total_mem=>"2001", :used_mem=>"390", :free_mem=>"1611"}
101
+ before gc: {:total_mem=>"2001", :used_mem=>"391", :free_mem=>"1610"}
102
+ before gc: {:total_mem=>"2001", :used_mem=>"392", :free_mem=>"1609"}
103
+ before gc: {:total_mem=>"2001", :used_mem=>"392", :free_mem=>"1609"}
104
+ before gc: {:total_mem=>"2001", :used_mem=>"392", :free_mem=>"1609"}
105
+ before gc: {:total_mem=>"2001", :used_mem=>"394", :free_mem=>"1607"}
106
+ before gc: {:total_mem=>"2001", :used_mem=>"394", :free_mem=>"1607"}
107
+ before gc: {:total_mem=>"2001", :used_mem=>"394", :free_mem=>"1607"}
108
+ before gc: {:total_mem=>"2001", :used_mem=>"393", :free_mem=>"1607"}
109
+ ...
110
+ after gc : {:total_mem=>"2001", :used_mem=>"421", :free_mem=>"1580"}
111
+ after gc : {:total_mem=>"2001", :used_mem=>"422", :free_mem=>"1579"}
112
+ after gc : {:total_mem=>"2001", :used_mem=>"425", :free_mem=>"1576"}
113
+ after gc : {:total_mem=>"2001", :used_mem=>"425", :free_mem=>"1576"}
114
+ after gc : {:total_mem=>"2001", :used_mem=>"424", :free_mem=>"1576"}
115
+ after gc : {:total_mem=>"2001", :used_mem=>"424", :free_mem=>"1577"}
116
+ after gc : {:total_mem=>"2001", :used_mem=>"422", :free_mem=>"1579"}
117
+ after gc : {:total_mem=>"2001", :used_mem=>"423", :free_mem=>"1578"}
118
+ after gc : {:total_mem=>"2001", :used_mem=>"423", :free_mem=>"1578"}
119
+ after gc : {:total_mem=>"2001", :used_mem=>"423", :free_mem=>"1578"}
120
+ after terminate all processes: {:total_mem=>"2001", :used_mem=>"385", :free_mem=>"1616"}
121
+
122
+ ruby 2.1.5p312 (2015-03-10 revision 49912) [x86_64-linux]
123
+ created 4194305 objects, consumed: 160 MB
124
+ before gc: {:total_mem=>"2001", :used_mem=>"308", :free_mem=>"1693"}
125
+ before gc: {:total_mem=>"2001", :used_mem=>"309", :free_mem=>"1692"}
126
+ before gc: {:total_mem=>"2001", :used_mem=>"313", :free_mem=>"1688"}
127
+ before gc: {:total_mem=>"2001", :used_mem=>"312", :free_mem=>"1689"}
128
+ before gc: {:total_mem=>"2001", :used_mem=>"313", :free_mem=>"1688"}
129
+ before gc: {:total_mem=>"2001", :used_mem=>"313", :free_mem=>"1688"}
130
+ before gc: {:total_mem=>"2001", :used_mem=>"313", :free_mem=>"1688"}
131
+ before gc: {:total_mem=>"2001", :used_mem=>"315", :free_mem=>"1686"}
132
+ before gc: {:total_mem=>"2001", :used_mem=>"314", :free_mem=>"1686"}
133
+ before gc: {:total_mem=>"2001", :used_mem=>"314", :free_mem=>"1686"}
134
+ ...
135
+ after gc : {:total_mem=>"2001", :used_mem=>"585", :free_mem=>"1416"}
136
+ after gc : {:total_mem=>"2001", :used_mem=>"587", :free_mem=>"1414"}
137
+ after gc : {:total_mem=>"2001", :used_mem=>"587", :free_mem=>"1414"}
138
+ after gc : {:total_mem=>"2001", :used_mem=>"587", :free_mem=>"1414"}
139
+ after gc : {:total_mem=>"2001", :used_mem=>"586", :free_mem=>"1415"}
140
+ after gc : {:total_mem=>"2001", :used_mem=>"586", :free_mem=>"1415"}
141
+ after gc : {:total_mem=>"2001", :used_mem=>"586", :free_mem=>"1415"}
142
+ after gc : {:total_mem=>"2001", :used_mem=>"586", :free_mem=>"1415"}
143
+ after gc : {:total_mem=>"2001", :used_mem=>"586", :free_mem=>"1415"}
144
+ after gc : {:total_mem=>"2001", :used_mem=>"586", :free_mem=>"1415"}
145
+ after terminate all processes: {:total_mem=>"2001", :used_mem=>"307", :free_mem=>"1694"}
146
+
147
+ ruby 2.2.3p134 (2015-06-15 revision 50899) [x86_64-linux]
148
+ created 4194304 objects, consumed: 160 MB
149
+ before gc: {:total_mem=>"2001", :used_mem=>"319", :free_mem=>"1682"}
150
+ before gc: {:total_mem=>"2001", :used_mem=>"321", :free_mem=>"1680"}
151
+ before gc: {:total_mem=>"2001", :used_mem=>"325", :free_mem=>"1675"}
152
+ before gc: {:total_mem=>"2001", :used_mem=>"335", :free_mem=>"1666"}
153
+ before gc: {:total_mem=>"2001", :used_mem=>"330", :free_mem=>"1671"}
154
+ before gc: {:total_mem=>"2001", :used_mem=>"351", :free_mem=>"1650"}
155
+ before gc: {:total_mem=>"2001", :used_mem=>"351", :free_mem=>"1650"}
156
+ before gc: {:total_mem=>"2001", :used_mem=>"353", :free_mem=>"1648"}
157
+ before gc: {:total_mem=>"2001", :used_mem=>"354", :free_mem=>"1647"}
158
+ before gc: {:total_mem=>"2001", :used_mem=>"354", :free_mem=>"1647"}
159
+ ...
160
+ after gc : {:total_mem=>"2001", :used_mem=>"1300", :free_mem=>"701"}
161
+ after gc : {:total_mem=>"2001", :used_mem=>"1300", :free_mem=>"701"}
162
+ after gc : {:total_mem=>"2001", :used_mem=>"1300", :free_mem=>"701"}
163
+ after gc : {:total_mem=>"2001", :used_mem=>"1302", :free_mem=>"699"}
164
+ after gc : {:total_mem=>"2001", :used_mem=>"1301", :free_mem=>"700"}
165
+ after gc : {:total_mem=>"2001", :used_mem=>"1302", :free_mem=>"699"}
166
+ after gc : {:total_mem=>"2001", :used_mem=>"1301", :free_mem=>"699"}
167
+ after gc : {:total_mem=>"2001", :used_mem=>"1301", :free_mem=>"699"}
168
+ after gc : {:total_mem=>"2001", :used_mem=>"1301", :free_mem=>"700"}
169
+ after gc : {:total_mem=>"2001", :used_mem=>"1300", :free_mem=>"700"}
170
+ after terminate all processes: {:total_mem=>"2001", :used_mem=>"307", :free_mem=>"1693"}
171
+
172
+ ruby 2.3.0dev (2015-08-16 trunk 51564) [x86_64-linux]
173
+ created 4194304 objects, consumed: 160 MB
174
+ before gc: {:total_mem=>"2001", :used_mem=>"310", :free_mem=>"1691"}
175
+ before gc: {:total_mem=>"2001", :used_mem=>"310", :free_mem=>"1691"}
176
+ before gc: {:total_mem=>"2001", :used_mem=>"310", :free_mem=>"1691"}
177
+ before gc: {:total_mem=>"2001", :used_mem=>"312", :free_mem=>"1689"}
178
+ before gc: {:total_mem=>"2001", :used_mem=>"311", :free_mem=>"1690"}
179
+ before gc: {:total_mem=>"2001", :used_mem=>"314", :free_mem=>"1687"}
180
+ before gc: {:total_mem=>"2001", :used_mem=>"315", :free_mem=>"1686"}
181
+ before gc: {:total_mem=>"2001", :used_mem=>"314", :free_mem=>"1687"}
182
+ before gc: {:total_mem=>"2001", :used_mem=>"316", :free_mem=>"1685"}
183
+ before gc: {:total_mem=>"2001", :used_mem=>"316", :free_mem=>"1685"}
184
+ ...
185
+ after gc : {:total_mem=>"2001", :used_mem=>"1268", :free_mem=>"732"}
186
+ after gc : {:total_mem=>"2001", :used_mem=>"1269", :free_mem=>"732"}
187
+ after gc : {:total_mem=>"2001", :used_mem=>"1269", :free_mem=>"732"}
188
+ after gc : {:total_mem=>"2001", :used_mem=>"1269", :free_mem=>"732"}
189
+ after gc : {:total_mem=>"2001", :used_mem=>"1270", :free_mem=>"731"}
190
+ after gc : {:total_mem=>"2001", :used_mem=>"1270", :free_mem=>"731"}
191
+ after gc : {:total_mem=>"2001", :used_mem=>"1270", :free_mem=>"731"}
192
+ after gc : {:total_mem=>"2001", :used_mem=>"1270", :free_mem=>"731"}
193
+ after gc : {:total_mem=>"2001", :used_mem=>"1269", :free_mem=>"731"}
194
+ after gc : {:total_mem=>"2001", :used_mem=>"1269", :free_mem=>"732"}
195
+ after terminate all processes: {:total_mem=>"2001", :used_mem=>"308", :free_mem=>"1693"}
196
+ ```
197
+
198
+ You can see Ruby 2.2 and Ruby 2.3 consume memory after fork+GC.
199
+
200
+ Using nakayoshi-fork:
201
+
202
+ ```
203
+ ruby 2.0.0p402 (2014-02-11) [x86_64-linux]
204
+ created 4194305 objects, consumed: 160 MB
205
+ before gc: {:total_mem=>"2001", :used_mem=>"391", :free_mem=>"1610"}
206
+ before gc: {:total_mem=>"2001", :used_mem=>"394", :free_mem=>"1607"}
207
+ before gc: {:total_mem=>"2001", :used_mem=>"394", :free_mem=>"1607"}
208
+ before gc: {:total_mem=>"2001", :used_mem=>"395", :free_mem=>"1606"}
209
+ before gc: {:total_mem=>"2001", :used_mem=>"397", :free_mem=>"1604"}
210
+ before gc: {:total_mem=>"2001", :used_mem=>"396", :free_mem=>"1605"}
211
+ before gc: {:total_mem=>"2001", :used_mem=>"397", :free_mem=>"1604"}
212
+ before gc: {:total_mem=>"2001", :used_mem=>"396", :free_mem=>"1604"}
213
+ before gc: {:total_mem=>"2001", :used_mem=>"397", :free_mem=>"1604"}
214
+ before gc: {:total_mem=>"2001", :used_mem=>"396", :free_mem=>"1605"}
215
+ ...
216
+ after gc : {:total_mem=>"2001", :used_mem=>"427", :free_mem=>"1574"}
217
+ after gc : {:total_mem=>"2001", :used_mem=>"426", :free_mem=>"1575"}
218
+ after gc : {:total_mem=>"2001", :used_mem=>"426", :free_mem=>"1575"}
219
+ after gc : {:total_mem=>"2001", :used_mem=>"425", :free_mem=>"1575"}
220
+ after gc : {:total_mem=>"2001", :used_mem=>"425", :free_mem=>"1575"}
221
+ after gc : {:total_mem=>"2001", :used_mem=>"426", :free_mem=>"1575"}
222
+ after gc : {:total_mem=>"2001", :used_mem=>"425", :free_mem=>"1575"}
223
+ after gc : {:total_mem=>"2001", :used_mem=>"426", :free_mem=>"1575"}
224
+ after gc : {:total_mem=>"2001", :used_mem=>"426", :free_mem=>"1575"}
225
+ after gc : {:total_mem=>"2001", :used_mem=>"426", :free_mem=>"1575"}
226
+ after terminate all processes: {:total_mem=>"2001", :used_mem=>"388", :free_mem=>"1613"}
227
+
228
+ ruby 2.1.5p312 (2015-03-10 revision 49912) [x86_64-linux]
229
+ created 4194305 objects, consumed: 160 MB
230
+ before gc: {:total_mem=>"2001", :used_mem=>"310", :free_mem=>"1690"}
231
+ before gc: {:total_mem=>"2001", :used_mem=>"313", :free_mem=>"1688"}
232
+ before gc: {:total_mem=>"2001", :used_mem=>"315", :free_mem=>"1685"}
233
+ before gc: {:total_mem=>"2001", :used_mem=>"315", :free_mem=>"1686"}
234
+ before gc: {:total_mem=>"2001", :used_mem=>"317", :free_mem=>"1683"}
235
+ before gc: {:total_mem=>"2001", :used_mem=>"317", :free_mem=>"1683"}
236
+ before gc: {:total_mem=>"2001", :used_mem=>"318", :free_mem=>"1683"}
237
+ before gc: {:total_mem=>"2001", :used_mem=>"318", :free_mem=>"1683"}
238
+ before gc: {:total_mem=>"2001", :used_mem=>"318", :free_mem=>"1683"}
239
+ before gc: {:total_mem=>"2001", :used_mem=>"318", :free_mem=>"1683"}
240
+ ...
241
+ after gc : {:total_mem=>"2001", :used_mem=>"363", :free_mem=>"1638"}
242
+ after gc : {:total_mem=>"2001", :used_mem=>"363", :free_mem=>"1638"}
243
+ after gc : {:total_mem=>"2001", :used_mem=>"363", :free_mem=>"1638"}
244
+ after gc : {:total_mem=>"2001", :used_mem=>"363", :free_mem=>"1638"}
245
+ after gc : {:total_mem=>"2001", :used_mem=>"363", :free_mem=>"1638"}
246
+ after gc : {:total_mem=>"2001", :used_mem=>"363", :free_mem=>"1638"}
247
+ after gc : {:total_mem=>"2001", :used_mem=>"363", :free_mem=>"1638"}
248
+ after gc : {:total_mem=>"2001", :used_mem=>"363", :free_mem=>"1637"}
249
+ after gc : {:total_mem=>"2001", :used_mem=>"363", :free_mem=>"1638"}
250
+ after gc : {:total_mem=>"2001", :used_mem=>"363", :free_mem=>"1638"}
251
+ after terminate all processes: {:total_mem=>"2001", :used_mem=>"310", :free_mem=>"1691"}
252
+
253
+ ruby 2.2.3p134 (2015-06-15 revision 50899) [x86_64-linux]
254
+ created 4194304 objects, consumed: 160 MB
255
+ before gc: {:total_mem=>"2001", :used_mem=>"311", :free_mem=>"1690"}
256
+ before gc: {:total_mem=>"2001", :used_mem=>"311", :free_mem=>"1690"}
257
+ before gc: {:total_mem=>"2001", :used_mem=>"314", :free_mem=>"1687"}
258
+ before gc: {:total_mem=>"2001", :used_mem=>"315", :free_mem=>"1686"}
259
+ before gc: {:total_mem=>"2001", :used_mem=>"315", :free_mem=>"1686"}
260
+ before gc: {:total_mem=>"2001", :used_mem=>"317", :free_mem=>"1684"}
261
+ before gc: {:total_mem=>"2001", :used_mem=>"317", :free_mem=>"1684"}
262
+ before gc: {:total_mem=>"2001", :used_mem=>"318", :free_mem=>"1683"}
263
+ before gc: {:total_mem=>"2001", :used_mem=>"318", :free_mem=>"1683"}
264
+ before gc: {:total_mem=>"2001", :used_mem=>"318", :free_mem=>"1683"}
265
+ ...
266
+ after gc : {:total_mem=>"2001", :used_mem=>"368", :free_mem=>"1633"}
267
+ after gc : {:total_mem=>"2001", :used_mem=>"368", :free_mem=>"1633"}
268
+ after gc : {:total_mem=>"2001", :used_mem=>"368", :free_mem=>"1633"}
269
+ after gc : {:total_mem=>"2001", :used_mem=>"368", :free_mem=>"1633"}
270
+ after gc : {:total_mem=>"2001", :used_mem=>"368", :free_mem=>"1633"}
271
+ after gc : {:total_mem=>"2001", :used_mem=>"368", :free_mem=>"1633"}
272
+ after gc : {:total_mem=>"2001", :used_mem=>"368", :free_mem=>"1633"}
273
+ after gc : {:total_mem=>"2001", :used_mem=>"369", :free_mem=>"1632"}
274
+ after gc : {:total_mem=>"2001", :used_mem=>"369", :free_mem=>"1632"}
275
+ after gc : {:total_mem=>"2001", :used_mem=>"369", :free_mem=>"1632"}
276
+ after terminate all processes: {:total_mem=>"2001", :used_mem=>"311", :free_mem=>"1690"}
277
+
278
+ ruby 2.3.0dev (2015-08-16 trunk 51564) [x86_64-linux]
279
+ created 4194304 objects, consumed: 160 MB
280
+ before gc: {:total_mem=>"2001", :used_mem=>"312", :free_mem=>"1689"}
281
+ before gc: {:total_mem=>"2001", :used_mem=>"313", :free_mem=>"1688"}
282
+ before gc: {:total_mem=>"2001", :used_mem=>"312", :free_mem=>"1689"}
283
+ before gc: {:total_mem=>"2001", :used_mem=>"315", :free_mem=>"1685"}
284
+ before gc: {:total_mem=>"2001", :used_mem=>"315", :free_mem=>"1686"}
285
+ before gc: {:total_mem=>"2001", :used_mem=>"317", :free_mem=>"1684"}
286
+ before gc: {:total_mem=>"2001", :used_mem=>"317", :free_mem=>"1684"}
287
+ before gc: {:total_mem=>"2001", :used_mem=>"318", :free_mem=>"1683"}
288
+ before gc: {:total_mem=>"2001", :used_mem=>"319", :free_mem=>"1682"}
289
+ before gc: {:total_mem=>"2001", :used_mem=>"319", :free_mem=>"1682"}
290
+ ...
291
+ after gc : {:total_mem=>"2001", :used_mem=>"361", :free_mem=>"1640"}
292
+ after gc : {:total_mem=>"2001", :used_mem=>"361", :free_mem=>"1640"}
293
+ after gc : {:total_mem=>"2001", :used_mem=>"361", :free_mem=>"1640"}
294
+ after gc : {:total_mem=>"2001", :used_mem=>"361", :free_mem=>"1640"}
295
+ after gc : {:total_mem=>"2001", :used_mem=>"362", :free_mem=>"1639"}
296
+ after gc : {:total_mem=>"2001", :used_mem=>"362", :free_mem=>"1639"}
297
+ after gc : {:total_mem=>"2001", :used_mem=>"362", :free_mem=>"1639"}
298
+ after gc : {:total_mem=>"2001", :used_mem=>"362", :free_mem=>"1639"}
299
+ after gc : {:total_mem=>"2001", :used_mem=>"362", :free_mem=>"1639"}
300
+ after gc : {:total_mem=>"2001", :used_mem=>"362", :free_mem=>"1639"}
301
+ after terminate all processes: {:total_mem=>"2001", :used_mem=>"310", :free_mem=>"1691"}
302
+ ```
303
+
304
+ You can see the improvement after GCs on MRI 2.2 and MRI 2.3-dev.
305
+
306
+ ## Contributing
307
+
308
+ 1. Fork it ( https://github.com/[my-github-username]/nakayoshi_fork/fork )
309
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
310
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
311
+ 4. Push to the branch (`git push origin my-new-feature`)
312
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,24 @@
1
+ require "nakayoshi_fork/version"
2
+
3
+ module NakayoshiFork
4
+ def fork(nakayoshi: true, cow_friendly: true, &b)
5
+ if nakayoshi && cow_friendly
6
+ h = {}
7
+ 3.times{ # maximum 3 times
8
+ GC.stat(h)
9
+ live_slots = h[:heap_live_slots] || h[:heap_live_slot]
10
+ old_objects = h[:old_objects] || h[:old_object]
11
+ remwb_unprotects = h[:remembered_wb_unprotected_objects] || h[:remembered_shady_object]
12
+ young_objects = live_slots - old_objects - remwb_unprotects
13
+ break if young_objects < live_slots / 10
14
+ GC.start(full_mark: false)
15
+ }
16
+ end
17
+
18
+ super(&b)
19
+ end if GC.method(:start).arity != 0
20
+ end
21
+
22
+ class Object
23
+ prepend NakayoshiFork
24
+ end
@@ -0,0 +1,3 @@
1
+ module NakayoshiFork
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'nakayoshi_fork/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "nakayoshi_fork"
8
+ spec.version = NakayoshiFork::VERSION
9
+ spec.authors = ["Koichi Sasada"]
10
+ spec.email = ["ko1@atdot.net"]
11
+ spec.summary = %q{nakayoshi_fork gem solves CoW friendly problem on MRI 2.2 and later.}
12
+ spec.description = %q{nakayoshi_fork gem solves CoW friendly problem on MRI 2.2 and later.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nakayoshi_fork
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Koichi Sasada
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-08-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: nakayoshi_fork gem solves CoW friendly problem on MRI 2.2 and later.
42
+ email:
43
+ - ko1@atdot.net
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - lib/nakayoshi_fork.rb
54
+ - lib/nakayoshi_fork/version.rb
55
+ - nakayoshi_fork.gemspec
56
+ homepage: ''
57
+ licenses:
58
+ - MIT
59
+ metadata: {}
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project:
76
+ rubygems_version: 2.5.0
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: nakayoshi_fork gem solves CoW friendly problem on MRI 2.2 and later.
80
+ test_files: []