rblineprof 0.2.0 → 0.2.1
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.
- data/README.md +25 -22
- data/ext/rblineprof.c +56 -28
- data/rblineprof.gemspec +1 -1
- data/test.rb +8 -3
- metadata +4 -4
data/README.md
CHANGED
@@ -4,28 +4,31 @@
|
|
4
4
|
% ruby -C ext extconf.rb
|
5
5
|
% make -C ext
|
6
6
|
% ruby test.rb
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
1 |
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
7
|
+
| $:.unshift 'ext'
|
8
|
+
| require 'rblineprof'
|
9
|
+
|
|
10
|
+
| profile = lineprof(/./) do
|
11
|
+
1.2ms | sleep 0.001
|
12
|
+
|
|
13
|
+
0.1ms | 100.times do
|
14
|
+
|
|
15
|
+
119.6ms | sleep 0.001
|
16
|
+
0.7ms | 1*2*3
|
17
|
+
0.2ms | 4*5*6
|
18
|
+
0.4ms | 7*8*9*10*11*12*13*14*15
|
19
|
+
0.2ms | 2**32
|
20
|
+
1.4ms | 2**128
|
21
|
+
|
|
22
|
+
| end
|
23
|
+
| end
|
24
|
+
|
|
25
|
+
| File.readlines(__FILE__).each_with_index do |line, num|
|
26
|
+
| if (sample = profile[__FILE__][num+1]) > 0
|
27
|
+
| printf "% 8.1fms | %s", sample/1000.0, line
|
28
|
+
| else
|
29
|
+
| printf " | %s", line
|
30
|
+
| end
|
31
|
+
| end
|
29
32
|
```
|
30
33
|
|
31
34
|
## Other profilers
|
data/ext/rblineprof.c
CHANGED
@@ -22,6 +22,8 @@ typedef struct {
|
|
22
22
|
|
23
23
|
static struct {
|
24
24
|
bool enabled;
|
25
|
+
char *last_file;
|
26
|
+
long last_line;
|
25
27
|
|
26
28
|
// single file mode, store filename and line data directly
|
27
29
|
char *source_filename;
|
@@ -30,14 +32,16 @@ static struct {
|
|
30
32
|
// regex mode, store file data in hash table
|
31
33
|
VALUE source_regex;
|
32
34
|
st_table *files;
|
33
|
-
sourcefile_t *
|
35
|
+
sourcefile_t *last_sourcefile;
|
34
36
|
}
|
35
37
|
rblineprof = {
|
36
38
|
.enabled = false,
|
39
|
+
.last_file = NULL,
|
40
|
+
.last_line = 0,
|
37
41
|
.source_filename = NULL,
|
38
42
|
.source_regex = Qfalse,
|
39
43
|
.files = NULL,
|
40
|
-
.
|
44
|
+
.last_sourcefile = NULL
|
41
45
|
};
|
42
46
|
|
43
47
|
static uint64_t
|
@@ -49,17 +53,51 @@ timeofday_usec()
|
|
49
53
|
(uint64_t)tv.tv_usec;
|
50
54
|
}
|
51
55
|
|
56
|
+
static inline void
|
57
|
+
sourcefile_record(sourcefile_t *sourcefile, uint64_t now)
|
58
|
+
{
|
59
|
+
if (sourcefile->last_time && sourcefile->last_line) {
|
60
|
+
/* allocate space for per-line data the first time */
|
61
|
+
if (sourcefile->lines == NULL) {
|
62
|
+
sourcefile->nlines = sourcefile->last_line + 100;
|
63
|
+
sourcefile->lines = ALLOC_N(uint64_t, sourcefile->nlines);
|
64
|
+
MEMZERO(sourcefile->lines, uint64_t, sourcefile->nlines);
|
65
|
+
}
|
66
|
+
|
67
|
+
/* grow the per-line array if necessary */
|
68
|
+
if (sourcefile->last_line >= sourcefile->nlines) {
|
69
|
+
long prev_nlines = sourcefile->nlines;
|
70
|
+
sourcefile->nlines = sourcefile->last_line + 100;
|
71
|
+
|
72
|
+
REALLOC_N(sourcefile->lines, uint64_t, sourcefile->nlines);
|
73
|
+
MEMZERO(sourcefile->lines + prev_nlines, uint64_t, sourcefile->nlines - prev_nlines);
|
74
|
+
}
|
75
|
+
|
76
|
+
/* record the sample */
|
77
|
+
sourcefile->lines[sourcefile->last_line] += (now - sourcefile->last_time);
|
78
|
+
sourcefile->last_time = now;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
52
82
|
static void
|
53
83
|
profiler_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
54
84
|
{
|
55
85
|
sourcefile_t *sourcefile = NULL;
|
56
86
|
|
87
|
+
if (!node) return;
|
88
|
+
|
57
89
|
char *file = node->nd_file;
|
58
90
|
long line = nd_line(node);
|
59
91
|
|
60
92
|
if (!file) return;
|
61
93
|
if (line <= 0) return;
|
62
94
|
|
95
|
+
// skip duplicate events fast
|
96
|
+
if (file == rblineprof.last_file && line == rblineprof.last_line)
|
97
|
+
return;
|
98
|
+
rblineprof.last_file = file;
|
99
|
+
rblineprof.last_line = line;
|
100
|
+
|
63
101
|
if (rblineprof.source_filename) { // single file mode
|
64
102
|
if (rblineprof.source_filename == file) {
|
65
103
|
sourcefile = &rblineprof.file;
|
@@ -90,34 +128,22 @@ profiler_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
90
128
|
if (sourcefile) {
|
91
129
|
uint64_t now = timeofday_usec();
|
92
130
|
|
93
|
-
if
|
94
|
-
|
95
|
-
|
96
|
-
sourcefile->nlines = sourcefile->last_line + 100;
|
97
|
-
sourcefile->lines = ALLOC_N(uint64_t, sourcefile->nlines);
|
98
|
-
MEMZERO(sourcefile->lines, uint64_t, sourcefile->nlines);
|
99
|
-
}
|
100
|
-
|
101
|
-
/* grow the per-line array if necessary */
|
102
|
-
if (sourcefile->last_line >= sourcefile->nlines) {
|
103
|
-
long prev_nlines = sourcefile->nlines;
|
104
|
-
sourcefile->nlines = sourcefile->last_line + 100;
|
105
|
-
|
106
|
-
REALLOC_N(sourcefile->lines, uint64_t, sourcefile->nlines);
|
107
|
-
MEMZERO(sourcefile->lines + prev_nlines, uint64_t, sourcefile->nlines - prev_nlines);
|
108
|
-
}
|
109
|
-
|
110
|
-
/* record the sample */
|
111
|
-
sourcefile->lines[sourcefile->last_line] += (now - sourcefile->last_time);
|
131
|
+
/* increment if the line in the current file changed */
|
132
|
+
if (sourcefile->last_line != line) {
|
133
|
+
sourcefile_record(sourcefile, now);
|
112
134
|
}
|
113
|
-
|
114
|
-
sourcefile->last_time = now;
|
115
135
|
sourcefile->last_line = line;
|
116
136
|
|
117
|
-
if (
|
118
|
-
|
137
|
+
if (!sourcefile->last_time)
|
138
|
+
sourcefile->last_time = now;
|
139
|
+
|
140
|
+
/* if we came from another file, increment there and reset */
|
141
|
+
if (rblineprof.last_sourcefile && rblineprof.last_sourcefile != sourcefile) {
|
142
|
+
sourcefile_record(rblineprof.last_sourcefile, now);
|
143
|
+
rblineprof.last_sourcefile->last_line = 0;
|
144
|
+
}
|
119
145
|
|
120
|
-
rblineprof.
|
146
|
+
rblineprof.last_sourcefile = sourcefile;
|
121
147
|
}
|
122
148
|
}
|
123
149
|
|
@@ -181,8 +207,10 @@ lineprof(VALUE self, VALUE filename)
|
|
181
207
|
rb_raise(rb_eArgError, "argument must be String or Regexp");
|
182
208
|
}
|
183
209
|
|
184
|
-
//
|
210
|
+
// reset state
|
185
211
|
rblineprof.last_file = NULL;
|
212
|
+
rblineprof.last_line = 0;
|
213
|
+
rblineprof.last_sourcefile = NULL;
|
186
214
|
st_foreach(rblineprof.files, cleanup_files, 0);
|
187
215
|
if (rblineprof.file.lines) {
|
188
216
|
xfree(rblineprof.file.lines);
|
@@ -191,7 +219,7 @@ lineprof(VALUE self, VALUE filename)
|
|
191
219
|
}
|
192
220
|
|
193
221
|
rblineprof.enabled = true;
|
194
|
-
rb_add_event_hook(profiler_hook,
|
222
|
+
rb_add_event_hook(profiler_hook, RUBY_EVENT_ALL);
|
195
223
|
rb_ensure(rb_yield, Qnil, lineprof_ensure, self);
|
196
224
|
|
197
225
|
VALUE ret = rb_hash_new();
|
data/rblineprof.gemspec
CHANGED
data/test.rb
CHANGED
@@ -2,8 +2,11 @@ $:.unshift 'ext'
|
|
2
2
|
require 'rblineprof'
|
3
3
|
|
4
4
|
profile = lineprof(/./) do
|
5
|
-
|
5
|
+
sleep 0.001
|
6
6
|
|
7
|
+
100.times do
|
8
|
+
|
9
|
+
sleep 0.001
|
7
10
|
1*2*3
|
8
11
|
4*5*6
|
9
12
|
7*8*9*10*11*12*13*14*15
|
@@ -15,8 +18,10 @@ end
|
|
15
18
|
|
16
19
|
File.readlines(__FILE__).each_with_index do |line, num|
|
17
20
|
if (sample = profile[__FILE__][num+1]) > 0
|
18
|
-
printf "%
|
21
|
+
# printf "% 7d | %s", sample, line
|
22
|
+
printf "% 8.1fms | %s", sample/1000.0, line
|
19
23
|
else
|
20
|
-
printf "
|
24
|
+
# printf " | %s", line
|
25
|
+
printf " | %s", line
|
21
26
|
end
|
22
27
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rblineprof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 1
|
10
|
+
version: 0.2.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Aman Gupta
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-09-
|
18
|
+
date: 2012-09-24 00:00:00 Z
|
19
19
|
dependencies: []
|
20
20
|
|
21
21
|
description: rblineprof shows you lines of code that are slow.
|