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