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 +4 -4
- data/.gitignore +4 -0
- data/Gemfile.lock +2 -2
- data/ext/tacho/tacho.c +60 -13
- data/ext/tacho/tacho.h +17 -7
- data/lib/tacho.rb +2 -2
- data/lib/tacho/version.rb +1 -1
- data/tacho.gemspec +1 -1
- data/tacho/.gitkeep +0 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: abd0c2672497503b4b9f2777d4e4ba0bb93d8b720ba301d5412e32072b8dc029
|
4
|
+
data.tar.gz: 6f1be7d8c34c8b749910791a6ae4d2cab3db2380e7880116502cb65401cbe411
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2366e1ddd9aee11f190bc0d5e2aeb3ef2e625ab990a3cbf223f827fcf5a6970f07bf1076119ecee336256362e680a3de81df8c84005082e7e62f3e43446e6fbb
|
7
|
+
data.tar.gz: 640a07df5a1be26d25edf9e8cb81a4a7c76de84bd7ee37ce55bcaebae12ba0d4837692faea8bcfa4660f7dc56ebe8e399e45dd1d76bad080360904213d0b6ab6
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
tacho (0.1.
|
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
|
data/ext/tacho/tacho.c
CHANGED
@@ -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(
|
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
|
-
|
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(
|
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,
|
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
|
}
|
data/ext/tacho/tacho.h
CHANGED
@@ -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
|
15
|
+
#define CALL_BODY_BYTES 14
|
15
16
|
|
16
17
|
typedef struct {
|
17
|
-
|
18
|
+
uint32_t thread_id;
|
19
|
+
uint32_t fiber_id;
|
20
|
+
} tch_thread_switch;
|
21
|
+
#define THREAD_SWITCH_BYTES 8
|
18
22
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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 */
|
data/lib/tacho.rb
CHANGED
@@ -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
|
data/lib/tacho/version.rb
CHANGED
data/tacho.gemspec
CHANGED
@@ -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
|
data/tacho/.gitkeep
ADDED
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.
|
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-
|
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
|