tacho 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 649ae475b526cb6a76fec040c7ba1f1519a1035a980eecc51b3b57fb593ca950
4
- data.tar.gz: d16cce60864b220c7b376dd4248f35cce5584f56332cd716d3db9ad0943b76e4
3
+ metadata.gz: abd0c2672497503b4b9f2777d4e4ba0bb93d8b720ba301d5412e32072b8dc029
4
+ data.tar.gz: 6f1be7d8c34c8b749910791a6ae4d2cab3db2380e7880116502cb65401cbe411
5
5
  SHA512:
6
- metadata.gz: 6eaea8985e1dcbdb92156fe6ef0655978a94a960a3ebb119c91ddd769e9ecb0f042d39b48956c17dd64ca1d38c94dbbb569174a1758160b9ab93d377a24d0316
7
- data.tar.gz: 7587dd2b0b9a843981cf083ba38abb54529e2c890906cb2d5b3114a4155a98046b24d875c9c5573919bb7c6febc01904cf788161519db8764466d6d19f596cfa
6
+ metadata.gz: 2366e1ddd9aee11f190bc0d5e2aeb3ef2e625ab990a3cbf223f827fcf5a6970f07bf1076119ecee336256362e680a3de81df8c84005082e7e62f3e43446e6fbb
7
+ data.tar.gz: 640a07df5a1be26d25edf9e8cb81a4a7c76de84bd7ee37ce55bcaebae12ba0d4837692faea8bcfa4660f7dc56ebe8e399e45dd1d76bad080360904213d0b6ab6
data/.gitignore CHANGED
@@ -12,4 +12,8 @@
12
12
  *.a
13
13
  mkmf.log
14
14
 
15
+ *.gem
16
+
17
+ tacho/*.tch
18
+
15
19
  .idea/
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tacho (0.1.0)
4
+ tacho (0.1.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -18,7 +18,7 @@ DEPENDENCIES
18
18
  bundler (~> 1.17)
19
19
  minitest (~> 5.0)
20
20
  rake (~> 10.0)
21
- rake-compiler
21
+ rake-compiler (~> 1.0)
22
22
  tacho!
23
23
 
24
24
  BUNDLED WITH
@@ -3,11 +3,35 @@
3
3
  #include <ruby/ruby.h>
4
4
  #include <ruby/debug.h>
5
5
 
6
+ VALUE rb_mTacho;
7
+ VALUE rb_cTachoProfile;
8
+ ID id_wall;
9
+ ID id_process;
10
+ ID id_thread;
11
+
6
12
  static inline void write_header(tch_profile* profile, char type, uint64_t time) {
7
13
  uint64_t c = ((time - profile->start_time) << 8) | type;
8
14
  fwrite(&c, sizeof(uint64_t), 1, profile->output);
9
15
  }
10
16
 
17
+ static inline void write_thread_switch_maybe(tch_profile* profile) {
18
+ char c = 'T';
19
+ tch_thread_switch thread_switch;
20
+ VALUE thread = rb_thread_current();
21
+ VALUE fiber = rb_fiber_current();
22
+
23
+ thread_switch.thread_id = rb_obj_id(thread);
24
+ thread_switch.fiber_id = rb_obj_id(fiber);
25
+
26
+ if (thread_switch.thread_id != profile->last_thread_id || thread_switch.fiber_id != profile->last_fiber_id) {
27
+ profile->last_thread_id = thread_switch.thread_id;
28
+ profile->last_fiber_id = thread_switch.fiber_id;
29
+
30
+ fwrite(&c, 1, 1, profile->output);
31
+ fwrite(&thread_switch, sizeof(tch_thread_switch), 1, profile->output);
32
+ }
33
+ }
34
+
11
35
  static void tacho_event(VALUE tpval, void *data) {
12
36
  tch_profile* profile = (tch_profile*)data;
13
37
 
@@ -25,17 +49,17 @@ static void tacho_event(VALUE tpval, void *data) {
25
49
  char* cur_str;
26
50
  int i;
27
51
 
52
+ uint32_t return_body;
28
53
  tch_call_body call_body;
29
54
 
30
- rb_trace_arg_t* trace_arg;
31
- rb_event_flag_t event_flag;
32
-
33
- trace_arg = rb_tracearg_from_tracepoint(tpval);
34
- event_flag = rb_tracearg_event_flag(trace_arg);
55
+ rb_trace_arg_t* trace_arg = rb_tracearg_from_tracepoint(tpval);
56
+ rb_event_flag_t event_flag = rb_tracearg_event_flag(trace_arg);
35
57
 
36
- clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time);
58
+ clock_gettime(profile->clock_type, &time);
37
59
  itime = (long)time.tv_sec * 1000000000 + (long)time.tv_nsec;
38
60
 
61
+ write_thread_switch_maybe(profile);
62
+
39
63
  if (event_flag == RUBY_EVENT_CALL) {
40
64
  write_header(profile, 'C', itime);
41
65
  call_body.line_no = FIX2INT(rb_tracearg_lineno(trace_arg));
@@ -43,6 +67,7 @@ static void tacho_event(VALUE tpval, void *data) {
43
67
  path = rb_tracearg_path(trace_arg);
44
68
 
45
69
  method_id = SYM2ID(rb_tracearg_method_id(trace_arg));
70
+ call_body.method_id = method_id;
46
71
 
47
72
  method_name = rb_id2name(method_id);
48
73
  method_length = strlen(method_name);
@@ -67,12 +92,12 @@ static void tacho_event(VALUE tpval, void *data) {
67
92
  fwrite(cur_str, call_body.filename_length, 1, profile->output);
68
93
  } else if (event_flag == RUBY_EVENT_RETURN) {
69
94
  write_header(profile, 'R', itime);
95
+
96
+ return_body = SYM2ID(rb_tracearg_method_id(trace_arg));
97
+ fwrite(&return_body, sizeof(uint32_t), 1, profile->output);
70
98
  }
71
99
  }
72
100
 
73
- VALUE rb_mTacho;
74
- VALUE rb_cTachoProfile;
75
-
76
101
  static tch_profile* tch_profile_get_profile(VALUE self) {
77
102
  return (tch_profile*)RDATA(self)->data;
78
103
  }
@@ -107,11 +132,12 @@ static VALUE tch_profile_initialize(VALUE self) {
107
132
  return self;
108
133
  }
109
134
 
110
- static VALUE tch_profile_start(VALUE self, VALUE filename, VALUE name) {
135
+ static VALUE tch_profile_start(VALUE self, VALUE filename, VALUE name, VALUE clock_type) {
111
136
  tch_profile* profile = tch_profile_get_profile(self);
112
137
 
113
138
  struct timespec time;
114
139
  uint32_t name_length;
140
+ ID clock_type_id;
115
141
 
116
142
  profile->output = fopen(StringValueCStr(filename), "wb");
117
143
  profile->buffer_count = 0;
@@ -125,7 +151,24 @@ static VALUE tch_profile_start(VALUE self, VALUE filename, VALUE name) {
125
151
 
126
152
  profile->recording = 1;
127
153
 
128
- clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time);
154
+ if (NIL_P(clock_type)) {
155
+ profile->clock_type = CLOCK_MONOTONIC;
156
+ } else if (TYPE(clock_type) == T_SYMBOL) {
157
+ clock_type_id = SYM2ID(clock_type);
158
+ if (id_wall == clock_type_id) {
159
+ profile->clock_type = CLOCK_MONOTONIC;
160
+ } else if (id_process == clock_type_id) {
161
+ profile->clock_type = CLOCK_PROCESS_CPUTIME_ID;
162
+ } else if (id_thread == clock_type_id) {
163
+ profile->clock_type = CLOCK_THREAD_CPUTIME_ID;
164
+ } else {
165
+ rb_raise(rb_eTypeError, "not valid value. Must be one of :wall, :process or :thread got :%s", rb_id2name(clock_type_id));
166
+ }
167
+ } else {
168
+ rb_raise(rb_eTypeError, "not valid value. Must be a symbol of one of :wall, :process or :thread");
169
+ }
170
+
171
+ clock_gettime(profile->clock_type, &time);
129
172
  profile->start_time = (long)time.tv_sec * 1000000000 + (long)time.tv_nsec;
130
173
  write_header(profile, 'S', profile->start_time);
131
174
 
@@ -147,7 +190,7 @@ static VALUE tch_profile_stop(VALUE self) {
147
190
  uint64_t itime;
148
191
 
149
192
  if (profile->recording) {
150
- clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time);
193
+ clock_gettime(profile->clock_type, &time);
151
194
  itime = (long)time.tv_sec * 1000000000 + (long)time.tv_nsec;
152
195
  write_header(profile, 'F', itime);
153
196
 
@@ -171,6 +214,10 @@ Init_tacho(void) {
171
214
  rb_cTachoProfile = rb_define_class_under(rb_mTacho, "Profile", rb_cObject);
172
215
  rb_define_alloc_func(rb_cTachoProfile, tch_profile_allocate);
173
216
  rb_define_method(rb_cTachoProfile, "initialize", tch_profile_initialize, 0);
174
- rb_define_method(rb_cTachoProfile, "start", tch_profile_start, 2);
217
+ rb_define_method(rb_cTachoProfile, "start", tch_profile_start, 3);
175
218
  rb_define_method(rb_cTachoProfile, "stop", tch_profile_stop, 0);
219
+
220
+ id_wall = rb_intern("wall");
221
+ id_process = rb_intern("process");
222
+ id_thread = rb_intern("thread");
176
223
  }
@@ -7,20 +7,30 @@
7
7
 
8
8
  typedef struct {
9
9
  uint32_t line_no;
10
+ uint32_t method_id;
10
11
  uint16_t method_name_length;
11
12
  uint16_t filename_offset;
12
13
  uint16_t filename_length;
13
14
  } tch_call_body;
14
- #define CALL_BODY_BYTES 10
15
+ #define CALL_BODY_BYTES 14
15
16
 
16
17
  typedef struct {
17
- VALUE tracepoint;
18
+ uint32_t thread_id;
19
+ uint32_t fiber_id;
20
+ } tch_thread_switch;
21
+ #define THREAD_SWITCH_BYTES 8
18
22
 
19
- int recording;
20
- FILE* output;
21
- uint64_t start_time;
22
- int64_t buffer_count;
23
- char buffer[4096];
23
+ typedef struct {
24
+ VALUE tracepoint;
25
+ clockid_t clock_type;
26
+ int recording;
27
+ FILE* output;
28
+ uint64_t start_time;
29
+ int64_t buffer_count;
30
+ char buffer[4096];
31
+
32
+ uint32_t last_thread_id;
33
+ uint32_t last_fiber_id;
24
34
  } tch_profile;
25
35
 
26
36
  #endif /* TACHOMETER_H */
@@ -6,9 +6,9 @@ module Tacho
6
6
  class Error < StandardError;
7
7
  end
8
8
 
9
- def self.start(name = '')
9
+ def self.start(name = '', clock_type: :wall)
10
10
  profile = Profile.new()
11
- profile.start("tacho/#{Time.now.strftime("%Y%m%d_%H%M%S_%N")}.tch", name)
11
+ profile.start("tacho/#{Time.now.strftime("%Y%m%d_%H%M%S_%N")}.tch", name, clock_type)
12
12
  return profile
13
13
  end
14
14
  end
@@ -1,3 +1,3 @@
1
1
  module Tacho
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -38,6 +38,6 @@ Gem::Specification.new do |spec|
38
38
 
39
39
  spec.add_development_dependency "bundler", "~> 1.17"
40
40
  spec.add_development_dependency "rake", "~> 10.0"
41
- spec.add_development_dependency "rake-compiler", "~> 0"
41
+ spec.add_development_dependency "rake-compiler", "~> 1.0"
42
42
  spec.add_development_dependency "minitest", "~> 5.0"
43
43
  end
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tacho
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Divan Burger
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-08 00:00:00.000000000 Z
11
+ date: 2019-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '1.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '1.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: minitest
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -90,6 +90,7 @@ files:
90
90
  - lib/tacho/middleware.rb
91
91
  - lib/tacho/version.rb
92
92
  - tacho.gemspec
93
+ - tacho/.gitkeep
93
94
  homepage: https://github.com/divanburger/tacho
94
95
  licenses:
95
96
  - MIT