gc_tracer 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b9ce36d7506d6380617767354fcf92f131fb8eb2
4
- data.tar.gz: cd6eeb8447b71f3e4ceafd623af6bf0e793c45a7
3
+ metadata.gz: 08efc028ba431a430f1e0d1ac444b74884e575b4
4
+ data.tar.gz: 04aa0ea80b8ce757cd32bce97a84644740c6a53c
5
5
  SHA512:
6
- metadata.gz: 28c17973fe087d97552e5b12d0e8e0a3b43e0910e2591ae9144d3e6225bdd008da490777939b7d2cd97582a2fbc7e907b18b4c2517869fa65cad7ffb36fc1b66
7
- data.tar.gz: b27a89753bf65de227143b1e5966e131e5c47cc595cd90332f0265fa6c6bd28a35febfc5306fa7b0615dd93ae6c8aeeaa9c61db034eadcdb85beeaa867c64808
6
+ metadata.gz: 299a15128bd5794000a3d631e5ca21132dbe954192f19c71c5b5a18f3332271646375d108be07b516ef7f803dab65fcd932e862e435e9a3ba7ddd3c0329e95af
7
+ data.tar.gz: b6132a320def13c6161a4dcc7e105c21f167c82e6ad03af303dd4f9f2f9a00b874c8e253bf3f864a0978737d2673e588f946087faae8307e368eca702208e3e6
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+ - 2.2.0
data/README.md CHANGED
@@ -4,6 +4,8 @@ Trace Garbage Collector activities and output statistics information.
4
4
 
5
5
  This gem only supports MRI 2.1.0 and later.
6
6
 
7
+ [![Build Status](https://travis-ci.org/ko1/gc_tracer.svg)](https://travis-ci.org/ko1/gc_tracer)
8
+
7
9
  ## Installation
8
10
 
9
11
  Add this line to your application's Gemfile:
@@ -80,7 +82,7 @@ ensure
80
82
  end
81
83
  ```
82
84
 
83
- Default events are "start", "end_mark" and "end_sweep". You can specify
85
+ Default events are "start", "end_mark" and "end_sweep". You can specify
84
86
  what kind of information you want to collect.
85
87
 
86
88
  ```ruby
@@ -93,22 +95,48 @@ ensure
93
95
  end
94
96
  ```
95
97
 
96
- Above example means that no details information are not needed. Default
98
+ Above example means that no details information are not needed. Default
97
99
  setting is "gc_stat: true, gc_latest_gc_info: true, rusage: false".
98
100
 
99
- You can specify tick (time stamp) type with keyword parameter
100
- "tick_type". You can choose one of the tick type in :hw_counter, :time
101
+ You can specify tick (time stamp) type with keyword parameter
102
+ "tick_type". You can choose one of the tick type in :hw_counter, :time
101
103
  and :nano_time (if platform supports clock_gettime()).
102
104
 
103
105
  See lib/gc_tracer.rb for more details.
104
106
 
107
+ ### Custom fields
108
+
109
+ You can add custom fields.
110
+
111
+ ```ruby
112
+ GC::Tracer.start_logging(custom_fields: [:name1, :name2, ...]) do
113
+ # All fields are cleared by zero.
114
+
115
+ # You can increment values of each field.
116
+ GC::Tracer.custom_field_increment(:name1)
117
+ # It is equivalent to
118
+ # GC::Tracer.custom_field_set(:name1, GC::Tracer.custom_field_get(:name1))
119
+
120
+ # You can also decrement values
121
+ GC::Tracer.custom_field_decrement(:name1)
122
+
123
+ # Now, you can specify only Fixnum as field value.
124
+ GC::Tracer.custom_field_set(:name2, 123)
125
+
126
+ # You can specify an index instead of field name (faster than actual name)
127
+ GC::Tracer.custom_field_increment(0) # :name1
128
+ end
129
+ ```
130
+
131
+ Custom fields are printed as last columns.
132
+
105
133
  ### Custom events
106
134
 
107
- You can add custom events by your own. Calling
108
- `GC::Tracer.custom_event_logging(event_name)` in your program will puts
135
+ You can add custom events by your own. Calling
136
+ `GC::Tracer.custom_event_logging(event_name)` in your program will puts
109
137
  new statistics line into the logging file.
110
138
 
111
- For example, the following program insert 1000 custom event lines into
139
+ For example, the following program insert 1000 custom event lines into
112
140
  logging file (stderr for this type).
113
141
 
114
142
  ```ruby
@@ -120,7 +148,7 @@ GC::Tracer.start_logging(events: %i(start), gc_stat: false) do
120
148
  end
121
149
  ```
122
150
 
123
- This method is useful to trace where the GC events occur in your
151
+ This method is useful to trace where the GC events occur in your
124
152
  application.
125
153
 
126
154
 
@@ -66,6 +66,8 @@ tick(void)
66
66
  #define MAX_HOOKS 5
67
67
  #endif
68
68
 
69
+ #define MAX_CUSTOM_FIELDS 128
70
+
69
71
  static VALUE tracer_hooks[MAX_HOOKS];
70
72
  static VALUE tracer_acceptable_events[MAX_HOOKS];
71
73
 
@@ -77,12 +79,16 @@ struct gc_logging {
77
79
  int log_gc_stat;
78
80
  int log_gc_latest_gc_info;
79
81
  int log_rusage;
82
+ int log_custom_fields_count;
80
83
  } config;
81
84
 
82
85
  int enabled;
83
86
  VALUE enable_hooks[MAX_HOOKS]; /* Symbols */
84
87
  int enable_hooks_num; /* 0 to MAX_HOOKS */
85
88
 
89
+ ID custom_field_names[MAX_CUSTOM_FIELDS];
90
+ long custom_field_values[MAX_CUSTOM_FIELDS];
91
+
86
92
  FILE *out;
87
93
  const char *event;
88
94
 
@@ -138,6 +144,12 @@ out_sizet(FILE *out, size_t size)
138
144
  fprintf(out, "%lu\t", (unsigned long)size);
139
145
  }
140
146
 
147
+ static void
148
+ out_long(FILE *out, long l)
149
+ {
150
+ fprintf(out, "%ld\t", l);
151
+ }
152
+
141
153
  static double
142
154
  timeval2double(struct timeval *tv)
143
155
  {
@@ -303,6 +315,13 @@ out_stat(struct gc_logging *logging, const char *event)
303
315
  #if HAVE_GETRUSAGE
304
316
  if (logging->config.log_rusage) out_rusage(logging);
305
317
  #endif
318
+ if (logging->config.log_custom_fields_count > 0) {
319
+ int i;
320
+ for (i=0; i<logging->config.log_custom_fields_count; i++) {
321
+ out_long(logging->out, logging->custom_field_values[i]);
322
+ }
323
+ }
324
+
306
325
  out_terminate(logging->out);
307
326
  }
308
327
 
@@ -335,6 +354,12 @@ out_header(struct gc_logging *logging)
335
354
  out_header_each(logging, sym_rusage, sizeof(sym_rusage)/sizeof(VALUE));
336
355
  }
337
356
  #endif
357
+ if (logging->config.log_custom_fields_count > 0) {
358
+ int i;
359
+ for (i=0; i<logging->config.log_custom_fields_count; i++) {
360
+ out_str(logging->out, rb_id2name(logging->custom_field_names[i]));
361
+ }
362
+ }
338
363
  out_terminate(logging->out);
339
364
  }
340
365
 
@@ -540,6 +565,96 @@ gc_tracer_setup_logging_rusage(VALUE self, VALUE b)
540
565
  return self;
541
566
  }
542
567
 
568
+ static VALUE
569
+ gc_tracer_setup_logging_custom_fields(VALUE self, VALUE b)
570
+ {
571
+ struct gc_logging *logging = &trace_logging;
572
+
573
+ if (RTEST(b)) {
574
+ VALUE ary = rb_check_array_type(b);
575
+ int i;
576
+
577
+ logging->config.log_custom_fields_count = RARRAY_LEN(ary);
578
+
579
+ for (i=0; i<RARRAY_LEN(ary); i++) {
580
+ VALUE name = RARRAY_AREF(ary, i);
581
+ ID field_id = rb_to_id(name);
582
+
583
+ if (i >= MAX_CUSTOM_FIELDS) {
584
+ rb_raise(rb_eRuntimeError, "Number of custome fields exceeds %d", MAX_CUSTOM_FIELDS);
585
+ }
586
+
587
+ logging->custom_field_names[i] = field_id;
588
+ logging->custom_field_values[i] = 0;
589
+ }
590
+ }
591
+ else {
592
+ logging->config.log_custom_fields_count = 0;
593
+ }
594
+
595
+ return self;
596
+ }
597
+
598
+ static long *
599
+ custom_field_value_place(VALUE name)
600
+ {
601
+ struct gc_logging *logging = &trace_logging;
602
+ int index;
603
+
604
+ if (FIXNUM_P(name)) {
605
+ index = FIX2INT(name);
606
+ if (index >= logging->config.log_custom_fields_count) {
607
+ rb_raise(rb_eRuntimeError, "Only %d custom fields are available, but %d was specified",
608
+ logging->config.log_custom_fields_count, index);
609
+ }
610
+ }
611
+ else {
612
+ int i;
613
+ ID nid = rb_to_id(name);
614
+ for (i=0; i<logging->config.log_custom_fields_count; i++) {
615
+ if (nid == logging->custom_field_names[i]) {
616
+ index = i;
617
+ goto found;
618
+ }
619
+ }
620
+ rb_raise(rb_eRuntimeError, "Unkown custom fileds is specified.");
621
+ }
622
+ found:
623
+ return &logging->custom_field_values[index];
624
+ }
625
+
626
+ static VALUE
627
+ gc_tracer_custom_field_increment(VALUE self, VALUE name)
628
+ {
629
+ long *valp = custom_field_value_place(name);
630
+ (*valp)++;
631
+ return self;
632
+ }
633
+
634
+ static VALUE
635
+ gc_tracer_custom_field_decrement(VALUE self, VALUE name)
636
+ {
637
+ long *valp = custom_field_value_place(name);
638
+ (*valp)--;
639
+ return self;
640
+ }
641
+
642
+ static VALUE
643
+ gc_tracer_custom_field_get(VALUE self, VALUE name)
644
+ {
645
+ long *valp = custom_field_value_place(name);
646
+ return LONG2NUM(*valp);
647
+ }
648
+
649
+ static VALUE
650
+ gc_tracer_custom_field_set(VALUE self, VALUE name, VALUE val)
651
+ {
652
+ long *valp = custom_field_value_place(name);
653
+ long lval = NUM2LONG(val);
654
+ *valp = lval;
655
+ return val;
656
+ }
657
+
543
658
  static VALUE
544
659
  gc_tracer_start_logging(int argc, VALUE *argv, VALUE self)
545
660
  {
@@ -597,6 +712,13 @@ Init_gc_tracer_logging(VALUE mod)
597
712
  rb_define_module_function(mod, "setup_logging_gc_latest_gc_info=", gc_tracer_setup_logging_gc_latest_gc_info, 1);
598
713
  rb_define_module_function(mod, "setup_logging_rusage=", gc_tracer_setup_logging_rusage, 1);
599
714
 
715
+ /* custom fields */
716
+ rb_define_module_function(mod, "setup_looging_custom_fields=", gc_tracer_setup_logging_custom_fields, 1);
717
+ rb_define_module_function(mod, "custom_field_increment", gc_tracer_custom_field_increment, 1);
718
+ rb_define_module_function(mod, "custom_field_decrement", gc_tracer_custom_field_decrement, 1);
719
+ rb_define_module_function(mod, "custom_field_set", gc_tracer_custom_field_set, 2);
720
+ rb_define_module_function(mod, "custom_field_get", gc_tracer_custom_field_get, 1);
721
+
600
722
  /* custom event */
601
723
  rb_define_module_function(mod, "custom_event_logging", gc_tracer_custom_event_logging, 1);
602
724
 
data/lib/gc_tracer.rb CHANGED
@@ -12,7 +12,9 @@ module GC
12
12
  # collect information
13
13
  gc_stat: true,
14
14
  gc_latest_gc_info: true,
15
- rusage: false)
15
+ rusage: false,
16
+ custom_fields: nil
17
+ )
16
18
  # setup
17
19
  raise "do not specify two fienames" if filename && filename_opt
18
20
  setup_logging_out(filename_opt || filename)
@@ -22,6 +24,7 @@ module GC
22
24
  self.setup_logging_gc_latest_gc_info = gc_latest_gc_info
23
25
  self.setup_logging_rusage = rusage
24
26
  self.setup_logging_tick_type = tick_type
27
+ self.setup_looging_custom_fields = custom_fields
25
28
 
26
29
  if block_given?
27
30
  begin
@@ -1,3 +1,3 @@
1
1
  module GC::Tracer
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -28,6 +28,78 @@ describe GC::Tracer do
28
28
  it_behaves_like "logging_test"
29
29
  end
30
30
 
31
+ describe 'custom fields' do
32
+ describe 'manipulate values' do
33
+ around 'open' do |example|
34
+ Dir.mktmpdir('gc_tracer'){|dir|
35
+ logfile = "#{dir}/logging"
36
+ GC::Tracer.start_logging(logfile, custom_fields: %i(a b c)) do
37
+ example.run
38
+ end
39
+ }
40
+ end
41
+
42
+ it 'should raise error for unknown name or index' do
43
+ expect{GC::Tracer.custom_field_increment(:xyzzy)}.to raise_error RuntimeError
44
+ expect{GC::Tracer.custom_field_increment(42)}.to raise_error RuntimeError
45
+ end
46
+
47
+ it 'should count increments' do
48
+ GC::Tracer.custom_field_increment(:a)
49
+ GC::Tracer.custom_field_increment(:a)
50
+ GC::Tracer.custom_field_increment(:a)
51
+ GC::Tracer.custom_field_increment(0)
52
+ GC::Tracer.custom_field_increment(0)
53
+ GC::Tracer.custom_field_increment(0)
54
+
55
+ expect(GC::Tracer.custom_field_get(:a)).to be 6
56
+ expect(GC::Tracer.custom_field_get(0)).to be 6
57
+ end
58
+
59
+ it 'should count decments' do
60
+ GC::Tracer.custom_field_decrement(:b)
61
+ GC::Tracer.custom_field_decrement(:b)
62
+ GC::Tracer.custom_field_decrement(:b)
63
+ GC::Tracer.custom_field_decrement(1)
64
+ GC::Tracer.custom_field_decrement(1)
65
+ GC::Tracer.custom_field_decrement(1)
66
+
67
+ expect(GC::Tracer.custom_field_get(:b)).to be -6
68
+ expect(GC::Tracer.custom_field_get(1)).to be -6
69
+ end
70
+
71
+ it 'should set values' do
72
+ GC::Tracer.custom_field_set(:c, 42)
73
+ expect(GC::Tracer.custom_field_get(:c)).to be 42
74
+ GC::Tracer.custom_field_set(2, 43)
75
+ expect(GC::Tracer.custom_field_get(:c)).to be 43
76
+ end
77
+ end
78
+
79
+ describe 'output custome fields' do
80
+ it 'should output custome fields' do
81
+ Dir.mktmpdir('gc_tracer'){|dir|
82
+ logfile = "#{dir}/logging"
83
+ GC::Tracer.start_logging(logfile, custom_fields: %i(a b c)) do
84
+ GC::Tracer.custom_field_increment(:a)
85
+ GC::Tracer.custom_field_decrement(:b)
86
+ GC::Tracer.custom_event_logging("out")
87
+ end
88
+
89
+ expect(File.exist?(logfile)).to be_true
90
+ log = File.read(logfile)
91
+ expect(log.lines[0]).to match /a\tb\tc/
92
+ log.each_line{|line|
93
+ if /out/ =~ line
94
+ expect(line).to match /1\t-1\t0/
95
+ end
96
+ }
97
+ }
98
+ end
99
+ end
100
+ end
101
+
102
+
31
103
  =begin not supported now.
32
104
  shared_examples "objspace_recorder_test" do
33
105
  dirname = "gc_tracer_objspace_recorder_spec.#{$$}"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gc_tracer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Koichi Sasada
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-18 00:00:00.000000000 Z
11
+ date: 2015-04-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -76,6 +76,7 @@ extensions:
76
76
  extra_rdoc_files: []
77
77
  files:
78
78
  - ".gitignore"
79
+ - ".travis.yml"
79
80
  - Gemfile
80
81
  - LICENSE.txt
81
82
  - README.md
@@ -119,4 +120,3 @@ summary: gc_tracer gem adds GC::Tracer module.
119
120
  test_files:
120
121
  - spec/gc_tracer_spec.rb
121
122
  - spec/spec_helper.rb
122
- has_rdoc: