gc_tracer 0.0.2

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: 0bc50631646c163085a2c1122538138baf772b6a
4
+ data.tar.gz: f5f45aca16dc2820814c8b80bc13538ca8636291
5
+ SHA512:
6
+ metadata.gz: 090166b2f6544f9d7f72bc89d23cab974232faec13c50b7d70b9728e49bb857b6b50546c19269c9767c431f0100551fb06b78ac645b35ed2f0ebe9be7841857d
7
+ data.tar.gz: 4e6fe7b6c353439b664692f290f67e14fc0e0ad3190c5a9699292ff23afc82c904132dd2380726cb6683dd6c560faf5b1c2db7e7720fb9a7cbdb3b3d95860b44
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gc_tracer.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 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,56 @@
1
+ # GcTracer
2
+
3
+ gc-tracer gem add GC::Tracer module which trace GC activities and output
4
+ all statistics information.
5
+
6
+ This gem only supports MRI 2.1.0 and later.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'gc_tracer'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install gc_tracer
21
+
22
+ ## Usage
23
+
24
+ You can get GC statistics information like that:
25
+
26
+ require 'gc_tracer'
27
+ GC::Tracer.start_logging(filename) do
28
+ # do something
29
+ end
30
+
31
+ This code is equivalent to the following code.
32
+
33
+ require 'gc_tracer'
34
+ GC::Tracer.start_logging(filename)
35
+ # do something
36
+ GC::Tracer.stop_logging
37
+
38
+ In the stored file, you can get tab separated values about GC.stat() and
39
+ GC.latest_gc_info() at each events. Events are "GC starting time", "end
40
+ of marking time" and "end of sweeping time". For one GC, three lines
41
+ you can get.
42
+
43
+
44
+ ## Contributing
45
+
46
+ 1. Fork it ( http://github.com/ko1/gc_tracer/fork )
47
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
48
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
49
+ 4. Push to the branch (`git push origin my-new-feature`)
50
+ 5. Create new Pull Request
51
+
52
+
53
+ ## Credit
54
+
55
+ Originally created by Koichi Sasada.
56
+ Thank you Yuki Torii who helps me to make gem package.
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/extensiontask"
3
+ require 'rspec/core/rake_task'
4
+
5
+ spec = Gem::Specification.load('gc_tracer.gemspec')
6
+
7
+ Rake::ExtensionTask.new("gc_tracer", spec){|ext|
8
+ ext.lib_dir = "lib/gc_tracer"
9
+ }
10
+
11
+ RSpec::Core::RakeTask.new('spec' => 'compile')
12
+
13
+ task default: :spec
@@ -0,0 +1,21 @@
1
+ require 'mkmf'
2
+
3
+ # auto generation script
4
+ open("gc_tracer.h", 'w'){|f|
5
+ f.puts '#include "ruby/ruby.h"'
6
+ f.puts "static VALUE sym_gc_stat[#{GC.stat.keys.size}];"
7
+ f.puts "static VALUE sym_latest_gc_info[#{GC.latest_gc_info.keys.size}];"
8
+
9
+ f.puts "static void"
10
+ f.puts "setup_gc_trace_symbols(void)"
11
+ f.puts "{"
12
+ GC.stat.keys.each.with_index{|k, i|
13
+ f.puts " sym_gc_stat[#{i}] = ID2SYM(rb_intern(\"#{k}\"));"
14
+ }
15
+ GC.latest_gc_info.keys.each.with_index{|k, i|
16
+ f.puts " sym_latest_gc_info[#{i}] = ID2SYM(rb_intern(\"#{k}\"));"
17
+ }
18
+ f.puts "}"
19
+ }
20
+
21
+ create_makefile('gc_tracer/gc_tracer')
@@ -0,0 +1,310 @@
1
+ /*
2
+ * gc_tracer adds GC::Tracer module.
3
+ *
4
+ * By Koichi Sasada
5
+ * created at Wed Feb 26 10:52:59 2014.
6
+ */
7
+
8
+ #include "ruby/ruby.h"
9
+ #include "ruby/debug.h"
10
+ #include "gc_tracer.h"
11
+ #include "stdio.h"
12
+
13
+ static VALUE gc_start, gc_end_mark, gc_end_sweep;
14
+ static VALUE gc_trace_enabled;
15
+ static FILE *gc_trace_out = NULL;
16
+ static VALUE gc_trace_items, gc_trace_items_types;
17
+
18
+ enum gc_key_type {
19
+ GC_STAT_KEY,
20
+ GC_LATEST_GC_INFO_KEY
21
+ };
22
+
23
+ /* the following code is only for internal tuning. */
24
+
25
+ /* Source code to use RDTSC is quoted and modified from
26
+ * http://www.mcs.anl.gov/~kazutomo/rdtsc.html
27
+ * written by Kazutomo Yoshii <kazutomo@mcs.anl.gov>
28
+ */
29
+
30
+ #if defined(__GNUC__) && defined(__i386__)
31
+ typedef unsigned long long tick_t;
32
+
33
+ static inline tick_t
34
+ tick(void)
35
+ {
36
+ unsigned long long int x;
37
+ __asm__ __volatile__ ("rdtsc" : "=A" (x));
38
+ return x;
39
+ }
40
+
41
+ #elif defined(__GNUC__) && defined(__x86_64__)
42
+ typedef unsigned long long tick_t;
43
+
44
+ static __inline__ tick_t
45
+ tick(void)
46
+ {
47
+ unsigned long hi, lo;
48
+ __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
49
+ return ((unsigned long long)lo)|( ((unsigned long long)hi)<<32);
50
+ }
51
+
52
+ #elif defined(_WIN32) && defined(_MSC_VER)
53
+ #include <intrin.h>
54
+ typedef unsigned __int64 tick_t;
55
+
56
+ static inline tick_t
57
+ tick(void)
58
+ {
59
+ return __rdtsc();
60
+ }
61
+
62
+ #else /* use clock */
63
+ typedef clock_t tick_t;
64
+ static inline tick_t
65
+ tick(void)
66
+ {
67
+ return clock();
68
+ }
69
+ #endif
70
+
71
+ static tick_t start_tick;
72
+
73
+ static void
74
+ out_str(const char *str)
75
+ {
76
+ fprintf(gc_trace_out, "%s\t", str);
77
+ }
78
+
79
+ static void
80
+ out_terminate(void)
81
+ {
82
+ fprintf(gc_trace_out, "\n");
83
+ }
84
+
85
+ static void
86
+ out_sizet(size_t size)
87
+ {
88
+ fprintf(gc_trace_out, "%lu\t", (unsigned long)size);
89
+ }
90
+
91
+ static void
92
+ out_tick(void)
93
+ {
94
+ out_sizet(tick() - start_tick);
95
+ }
96
+
97
+ static void
98
+ out_obj(VALUE obj)
99
+ {
100
+ if (NIL_P(obj) || obj == Qfalse) {
101
+ out_sizet(0);
102
+ }
103
+ else if (obj == Qtrue) {
104
+ out_sizet(1);
105
+ }
106
+ else if (SYMBOL_P(obj)) {
107
+ out_str(rb_id2name(SYM2ID(obj)));
108
+ }
109
+ else if (FIXNUM_P(obj)) {
110
+ out_sizet(FIX2INT(obj));
111
+ }
112
+ else {
113
+ rb_bug("out_obj: unknown object to output");
114
+ }
115
+ }
116
+
117
+ static void
118
+ out_header(void)
119
+ {
120
+ int i;
121
+
122
+ out_str("tick");
123
+ out_str("type");
124
+
125
+ for (i=0; i<RARRAY_LEN(gc_trace_items); i++) {
126
+ out_str(rb_id2name(SYM2ID(RARRAY_AREF(gc_trace_items, i))));
127
+ }
128
+
129
+ out_terminate();
130
+ }
131
+
132
+ static void
133
+ trace(const char *type)
134
+ {
135
+ int i;
136
+
137
+ out_tick();
138
+ out_str(type);
139
+
140
+ for (i=0; i<RARRAY_LEN(gc_trace_items); i++) {
141
+ enum gc_key_type type = FIX2INT(RARRAY_AREF(gc_trace_items_types, i));
142
+ VALUE sym = RARRAY_AREF(gc_trace_items, i);
143
+
144
+ switch (type) {
145
+ case GC_STAT_KEY:
146
+ out_sizet(rb_gc_stat(sym));
147
+ break;
148
+ case GC_LATEST_GC_INFO_KEY:
149
+ out_obj(rb_gc_latest_gc_info(sym));
150
+ break;
151
+ default:
152
+ rb_bug("xyzzy");
153
+ }
154
+ }
155
+
156
+ out_terminate();
157
+ }
158
+
159
+ static void
160
+ gc_start_i(VALUE tpval, void *data)
161
+ {
162
+ trace("gc_start");
163
+ }
164
+
165
+ static void
166
+ gc_end_mark_i(VALUE tpval, void *data)
167
+ {
168
+ trace("gc_end_m");
169
+ }
170
+
171
+ static void
172
+ gc_end_sweep_i(VALUE tpval, void *data)
173
+ {
174
+ trace("gc_end_s");
175
+ }
176
+
177
+ static VALUE
178
+ gc_tracer_stop_logging(VALUE self)
179
+ {
180
+ if (gc_start != 0 && gc_trace_enabled != Qfalse) {
181
+ gc_trace_enabled = Qfalse;
182
+
183
+ fflush(gc_trace_out);
184
+ if (gc_trace_out != stderr) {
185
+ fclose(gc_trace_out);
186
+ }
187
+ gc_trace_out = NULL;
188
+
189
+ rb_tracepoint_disable(gc_start);
190
+ rb_tracepoint_disable(gc_end_mark);
191
+ rb_tracepoint_disable(gc_end_sweep);
192
+ }
193
+
194
+ return Qnil;
195
+ }
196
+
197
+ static VALUE
198
+ gc_tracer_start_logging(int argc, VALUE *argv, VALUE self)
199
+ {
200
+ if (gc_start == 0) {
201
+ gc_start = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_GC_START, gc_start_i, 0);
202
+ gc_end_mark = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_GC_END_MARK, gc_end_mark_i, 0);
203
+ gc_end_sweep = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_GC_END_SWEEP, gc_end_sweep_i, 0);
204
+
205
+ /* mark for GC */
206
+ rb_gc_register_mark_object(gc_start);
207
+ rb_gc_register_mark_object(gc_end_mark);
208
+ rb_gc_register_mark_object(gc_end_sweep);
209
+ }
210
+
211
+ if (gc_trace_enabled == Qfalse) {
212
+ gc_trace_enabled = Qtrue;
213
+
214
+ if (argc == 0) {
215
+ gc_trace_out = stderr;
216
+ }
217
+ else if (argc == 1) {
218
+ if (RB_TYPE_P(argv[0], T_STRING)) {
219
+ const char *filename = StringValueCStr(argv[0]);
220
+ if ((gc_trace_out = fopen(filename, "w")) == NULL) {
221
+ rb_raise(rb_eRuntimeError, "can not open file: %s\n", filename);
222
+ }
223
+ }
224
+ }
225
+ else {
226
+ rb_raise(rb_eArgError, "too many arguments");
227
+ }
228
+
229
+ rb_tracepoint_enable(gc_start);
230
+ rb_tracepoint_enable(gc_end_mark);
231
+ rb_tracepoint_enable(gc_end_sweep);
232
+
233
+ out_header();
234
+
235
+ if (rb_block_given_p()) {
236
+ rb_ensure(rb_yield, Qnil, gc_tracer_stop_logging, Qnil);
237
+ }
238
+ }
239
+
240
+ return Qnil;
241
+ }
242
+
243
+ static enum gc_key_type
244
+ item_type(VALUE sym)
245
+ {
246
+ int i;
247
+ for (i=0; i<(int)(sizeof(sym_gc_stat)/sizeof(VALUE));i++) {
248
+ return GC_STAT_KEY;
249
+ }
250
+ for (i=0; i<(int)(sizeof(sym_latest_gc_info)/sizeof(VALUE));i++) {
251
+ return GC_LATEST_GC_INFO_KEY;
252
+ }
253
+ rb_raise(rb_eArgError, "Unknown key type");
254
+ return 0; /* unreachable */
255
+ }
256
+
257
+ static VALUE
258
+ gc_tracer_setup_logging(VALUE self, VALUE ary)
259
+ {
260
+ int i;
261
+ VALUE keys = rb_ary_new(), types = rb_ary_new();
262
+
263
+ if (!RB_TYPE_P(ary, T_ARRAY)) rb_raise(rb_eArgError, "unsupported argument");
264
+
265
+ for (i=0; i<RARRAY_LEN(ary); i++) {
266
+ VALUE sym = RARRAY_AREF(ary, i);
267
+ enum gc_key_type type;
268
+ if (!SYMBOL_P(sym)) rb_raise(rb_eArgError, "unsupported type");
269
+ type = item_type(sym);
270
+ rb_ary_push(keys, sym);
271
+ rb_ary_push(types, INT2FIX(type));
272
+ }
273
+
274
+ rb_ary_replace(gc_trace_items, keys);
275
+ rb_ary_replace(gc_trace_items_types, types);
276
+ return Qnil;
277
+ }
278
+
279
+ void
280
+ Init_gc_tracer(void)
281
+ {
282
+ VALUE mod = rb_define_module_under(rb_mGC, "Tracer");
283
+
284
+ /* logging methods */
285
+ rb_define_module_function(mod, "start_logging", gc_tracer_start_logging, -1);
286
+ rb_define_module_function(mod, "stop_logging", gc_tracer_stop_logging, 0);
287
+ rb_define_module_function(mod, "setup_logging", gc_tracer_setup_logging, 1);
288
+
289
+ /* setup default banners */
290
+ setup_gc_trace_symbols();
291
+ start_tick = tick();
292
+ rb_gc_latest_gc_info(ID2SYM(rb_intern("gc_by"))); /* warm up */
293
+
294
+ gc_trace_items = rb_ary_new();
295
+ gc_trace_items_types = rb_ary_new();
296
+ rb_gc_register_mark_object(gc_trace_items);
297
+ rb_gc_register_mark_object(gc_trace_items_types);
298
+
299
+ {
300
+ int i;
301
+ for (i=0; i<(int)(sizeof(sym_gc_stat)/sizeof(VALUE));i++) {
302
+ rb_ary_push(gc_trace_items, sym_gc_stat[i]);
303
+ rb_ary_push(gc_trace_items_types, INT2FIX(GC_STAT_KEY));
304
+ }
305
+ for (i=0; i<(int)(sizeof(sym_latest_gc_info)/sizeof(VALUE));i++) {
306
+ rb_ary_push(gc_trace_items, sym_latest_gc_info[i]);
307
+ rb_ary_push(gc_trace_items_types, INT2FIX(GC_LATEST_GC_INFO_KEY));
308
+ }
309
+ }
310
+ }
data/gc_tracer.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gc_tracer/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "gc_tracer"
8
+ spec.version = GcTracer::VERSION
9
+ spec.authors = ["Koichi Sasada"]
10
+ spec.email = ["ko1@atdot.net"]
11
+ spec.summary = %q{gc_tracer gem adds GC::Tracer module.}
12
+ spec.description = %q{gc_tracer gem adds GC::Tracer module.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.extensions = %w[ext/gc_tracer/extconf.rb]
17
+ spec.required_ruby_version = '>= 2.1.0'
18
+
19
+ spec.files = `git ls-files -z`.split("\x0")
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.5"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rake-compiler"
27
+ spec.add_development_dependency "rspec"
28
+ end
@@ -0,0 +1,3 @@
1
+ module GcTracer
2
+ VERSION = "0.0.2"
3
+ end
data/lib/gc_tracer.rb ADDED
@@ -0,0 +1,3 @@
1
+ require "gc_tracer/version"
2
+ require 'gc_tracer/gc_tracer'
3
+
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+ require 'tmpdir'
3
+
4
+ describe GC::Tracer do
5
+ shared_examples "logging_test" do
6
+ it do
7
+ Dir.mktmpdir('gc_tracer'){|dir|
8
+ logfile = "#{dir}/logging"
9
+ GC::Tracer.start_logging(logfile){
10
+ count.times{
11
+ GC.start
12
+ }
13
+ }
14
+ expect(File.exist?(logfile)).to be_true
15
+ expect(File.read(logfile).split(/\n/).length).to be >= count * 3 + 1
16
+ }
17
+ end
18
+ end
19
+
20
+ context "1 GC.start" do
21
+ let(:count){1}
22
+ it_behaves_like "logging_test"
23
+ end
24
+
25
+ context "2 GC.start" do
26
+ let(:count){2}
27
+ it_behaves_like "logging_test"
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'gc_tracer'
4
+
5
+ RSpec.configure do |config|
6
+ config.mock_framework = :rspec
7
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gc_tracer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Koichi Sasada
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-25 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.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake-compiler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: gc_tracer gem adds GC::Tracer module.
70
+ email:
71
+ - ko1@atdot.net
72
+ executables: []
73
+ extensions:
74
+ - ext/gc_tracer/extconf.rb
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - ext/gc_tracer/extconf.rb
83
+ - ext/gc_tracer/gc_tracer.c
84
+ - gc_tracer.gemspec
85
+ - lib/gc_tracer.rb
86
+ - lib/gc_tracer/version.rb
87
+ - spec/gc_tracer_spec.rb
88
+ - spec/spec_helper.rb
89
+ homepage: ''
90
+ licenses:
91
+ - MIT
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: 2.1.0
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubyforge_project:
109
+ rubygems_version: 2.2.2
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: gc_tracer gem adds GC::Tracer module.
113
+ test_files:
114
+ - spec/gc_tracer_spec.rb
115
+ - spec/spec_helper.rb
116
+ has_rdoc: