tacho 0.1.0 → 0.1.2

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
  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