memprof 0.3.7 → 0.3.8
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/ext/memprof.c +22 -19
- data/ext/tracers/fd.c +59 -25
- data/ext/tracers/gc.c +6 -6
- data/ext/tracers/mysql.c +53 -6
- data/ext/tracers/postgres.c +19 -0
- data/ext/tracers/resources.c +10 -10
- data/ext/tracers/sql.c +56 -0
- data/ext/tracers/sql.h +18 -0
- data/ext/util.c +8 -0
- data/ext/util.h +8 -2
- data/memprof.gemspec +1 -1
- data/spec/tracing_spec.rb +3 -3
- metadata +6 -4
data/ext/memprof.c
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
#include <assert.h>
|
8
8
|
#include <err.h>
|
9
9
|
#include <fcntl.h>
|
10
|
+
#include <inttypes.h>
|
10
11
|
#include <stddef.h>
|
11
12
|
#include <stdint.h>
|
12
13
|
#include <stdio.h>
|
@@ -485,8 +486,9 @@ memprof_trace_request(VALUE self, VALUE env)
|
|
485
486
|
if (!rb_block_given_p())
|
486
487
|
rb_raise(rb_eArgError, "block required");
|
487
488
|
|
488
|
-
|
489
|
-
|
489
|
+
uint64_t start_time;
|
490
|
+
uint64_t end_time;
|
491
|
+
char str_time[32];
|
490
492
|
|
491
493
|
json_gen gen;
|
492
494
|
if (tracing_json_gen)
|
@@ -497,8 +499,9 @@ memprof_trace_request(VALUE self, VALUE env)
|
|
497
499
|
json_gen_map_open(gen);
|
498
500
|
|
499
501
|
json_gen_cstr(gen, "start");
|
500
|
-
|
501
|
-
|
502
|
+
start_time = timeofday_ms();
|
503
|
+
sprintf(str_time, "%" PRIu64, start_time);
|
504
|
+
json_gen_number(gen, str_time, strlen(str_time));
|
502
505
|
|
503
506
|
json_gen_cstr(gen, "tracers");
|
504
507
|
json_gen_map_open(gen);
|
@@ -507,32 +510,32 @@ memprof_trace_request(VALUE self, VALUE env)
|
|
507
510
|
trace_invoke_all(TRACE_RESET);
|
508
511
|
trace_invoke_all(TRACE_START);
|
509
512
|
|
510
|
-
|
513
|
+
start_time = timeofday_ms();
|
511
514
|
VALUE ret = rb_yield(Qnil);
|
512
|
-
|
515
|
+
end_time = timeofday_ms();
|
513
516
|
|
514
517
|
trace_invoke_all(TRACE_DUMP);
|
515
518
|
trace_invoke_all(TRACE_STOP);
|
516
519
|
|
517
520
|
json_gen_map_close(gen);
|
518
521
|
|
519
|
-
if (RTEST(env) &&
|
522
|
+
if (RTEST(env) && TYPE(env) == T_HASH) {
|
520
523
|
VALUE val, str;
|
521
524
|
val = rb_hash_aref(env, rb_str_new2("action_controller.request.path_parameters"));
|
522
525
|
if (!RTEST(val))
|
523
526
|
val = rb_hash_aref(env, rb_str_new2("action_dispatch.request.parameters"));
|
524
527
|
|
525
|
-
if (RTEST(val) &&
|
528
|
+
if (RTEST(val) && TYPE(val) == T_HASH) {
|
526
529
|
json_gen_cstr(gen, "rails");
|
527
530
|
json_gen_map_open(gen);
|
528
531
|
str = rb_hash_aref(val, rb_str_new2("controller"));
|
529
|
-
if (RTEST(str) &&
|
532
|
+
if (RTEST(str) && TYPE(str) == T_STRING) {
|
530
533
|
json_gen_cstr(gen, "controller");
|
531
534
|
json_gen_cstr(gen, RSTRING_PTR(str));
|
532
535
|
}
|
533
536
|
|
534
537
|
str = rb_hash_aref(val, rb_str_new2("action"));
|
535
|
-
if (RTEST(str) &&
|
538
|
+
if (RTEST(str) && TYPE(str) == T_STRING) {
|
536
539
|
json_gen_cstr(gen, "action");
|
537
540
|
json_gen_cstr(gen, RSTRING_PTR(str));
|
538
541
|
}
|
@@ -547,7 +550,7 @@ memprof_trace_request(VALUE self, VALUE env)
|
|
547
550
|
#define DUMP_HASH_ENTRY(key) do { \
|
548
551
|
str = rb_hash_aref(env, rb_str_new2(key)); \
|
549
552
|
if (RTEST(str) && \
|
550
|
-
|
553
|
+
TYPE(str) == T_STRING && \
|
551
554
|
RSTRING_PTR(str)) { \
|
552
555
|
json_gen_cstr(gen, key); \
|
553
556
|
json_gen_cstr(gen, RSTRING_PTR(str)); \
|
@@ -562,18 +565,18 @@ memprof_trace_request(VALUE self, VALUE env)
|
|
562
565
|
DUMP_HASH_ENTRY("QUERY_STRING");
|
563
566
|
|
564
567
|
json_gen_map_close(gen);
|
568
|
+
}
|
565
569
|
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
}
|
570
|
+
if (RTEST(ret) && TYPE(ret) == T_ARRAY) {
|
571
|
+
json_gen_cstr(gen, "response");
|
572
|
+
json_gen_map_open(gen);
|
573
|
+
json_gen_cstr(gen, "code");
|
574
|
+
json_gen_value(gen, RARRAY_PTR(ret)[0]);
|
575
|
+
json_gen_map_close(gen);
|
573
576
|
}
|
574
577
|
|
575
578
|
json_gen_cstr(gen, "time");
|
576
|
-
|
579
|
+
json_gen_integer(gen, end_time-start_time);
|
577
580
|
|
578
581
|
json_gen_map_close(gen);
|
579
582
|
json_gen_reset(gen);
|
data/ext/tracers/fd.c
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#include <assert.h>
|
2
2
|
#include <errno.h>
|
3
|
+
#include <poll.h>
|
3
4
|
#include <stdio.h>
|
4
5
|
#include <stdlib.h>
|
5
6
|
#include <string.h>
|
@@ -17,20 +18,23 @@
|
|
17
18
|
|
18
19
|
struct memprof_fd_stats {
|
19
20
|
size_t read_calls;
|
20
|
-
|
21
|
+
uint32_t read_time;
|
21
22
|
size_t read_requested_bytes;
|
22
23
|
size_t read_actual_bytes;
|
23
24
|
|
24
25
|
size_t write_calls;
|
25
|
-
|
26
|
+
uint32_t write_time;
|
26
27
|
size_t write_requested_bytes;
|
27
28
|
size_t write_actual_bytes;
|
28
29
|
|
29
30
|
size_t connect_calls;
|
30
|
-
|
31
|
+
uint32_t connect_time;
|
31
32
|
|
32
33
|
size_t select_calls;
|
33
|
-
|
34
|
+
uint32_t select_time;
|
35
|
+
|
36
|
+
size_t poll_calls;
|
37
|
+
uint32_t poll_time;
|
34
38
|
};
|
35
39
|
|
36
40
|
static struct tracer tracer;
|
@@ -38,16 +42,16 @@ static struct memprof_fd_stats stats;
|
|
38
42
|
|
39
43
|
static ssize_t
|
40
44
|
read_tramp(int fildes, void *buf, size_t nbyte) {
|
41
|
-
|
45
|
+
uint32_t millis = 0;
|
42
46
|
int err;
|
43
47
|
ssize_t ret;
|
44
48
|
|
45
|
-
|
49
|
+
millis = timeofday_ms();
|
46
50
|
ret = read(fildes, buf, nbyte);
|
47
51
|
err = errno;
|
48
|
-
|
52
|
+
millis = timeofday_ms() - millis;
|
49
53
|
|
50
|
-
stats.read_time +=
|
54
|
+
stats.read_time += millis;
|
51
55
|
stats.read_calls++;
|
52
56
|
stats.read_requested_bytes += nbyte;
|
53
57
|
if (ret > 0)
|
@@ -59,16 +63,16 @@ read_tramp(int fildes, void *buf, size_t nbyte) {
|
|
59
63
|
|
60
64
|
static ssize_t
|
61
65
|
write_tramp(int fildes, const void *buf, size_t nbyte) {
|
62
|
-
|
66
|
+
uint32_t millis = 0;
|
63
67
|
int err;
|
64
68
|
ssize_t ret;
|
65
69
|
|
66
|
-
|
70
|
+
millis = timeofday_ms();
|
67
71
|
ret = write(fildes, buf, nbyte);
|
68
72
|
err = errno;
|
69
|
-
|
73
|
+
millis = timeofday_ms() - millis;
|
70
74
|
|
71
|
-
stats.write_time +=
|
75
|
+
stats.write_time += millis;
|
72
76
|
stats.write_calls++;
|
73
77
|
stats.write_requested_bytes += nbyte;
|
74
78
|
if (ret > 0)
|
@@ -80,15 +84,15 @@ write_tramp(int fildes, const void *buf, size_t nbyte) {
|
|
80
84
|
|
81
85
|
static int
|
82
86
|
connect_tramp(int socket, const struct sockaddr *address, socklen_t address_len) {
|
83
|
-
|
87
|
+
uint32_t millis = 0;
|
84
88
|
int err, ret;
|
85
89
|
|
86
|
-
|
90
|
+
millis = timeofday_ms();
|
87
91
|
ret = connect(socket, address, address_len);
|
88
92
|
err = errno;
|
89
|
-
|
93
|
+
millis = timeofday_ms() - millis;
|
90
94
|
|
91
|
-
stats.connect_time +=
|
95
|
+
stats.connect_time += millis;
|
92
96
|
stats.connect_calls++;
|
93
97
|
|
94
98
|
errno = err;
|
@@ -98,21 +102,39 @@ connect_tramp(int socket, const struct sockaddr *address, socklen_t address_len)
|
|
98
102
|
static int
|
99
103
|
select_tramp(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)
|
100
104
|
{
|
101
|
-
|
105
|
+
uint32_t millis = 0;
|
102
106
|
int ret, err;
|
103
107
|
|
104
|
-
|
108
|
+
millis = timeofday_ms();
|
105
109
|
ret = select(nfds, readfds, writefds, errorfds, timeout);
|
106
110
|
err = errno;
|
107
|
-
|
111
|
+
millis = timeofday_ms() - millis;
|
108
112
|
|
109
|
-
stats.select_time +=
|
113
|
+
stats.select_time += millis;
|
110
114
|
stats.select_calls++;
|
111
115
|
|
112
116
|
errno = err;
|
113
117
|
return ret;
|
114
118
|
}
|
115
119
|
|
120
|
+
static int
|
121
|
+
poll_tramp(struct pollfd fds[], nfds_t nfds, int timeout)
|
122
|
+
{
|
123
|
+
uint32_t millis = 0;
|
124
|
+
int ret, err;
|
125
|
+
|
126
|
+
millis = timeofday_ms();
|
127
|
+
ret = poll(fds, nfds, timeout);
|
128
|
+
err = errno;
|
129
|
+
millis = timeofday_ms() - millis;
|
130
|
+
|
131
|
+
stats.poll_time += millis;
|
132
|
+
stats.poll_calls++;
|
133
|
+
|
134
|
+
errno = err;
|
135
|
+
return ret;
|
136
|
+
}
|
137
|
+
|
116
138
|
static void
|
117
139
|
fd_trace_start() {
|
118
140
|
static int inserted = 0;
|
@@ -124,11 +146,13 @@ fd_trace_start() {
|
|
124
146
|
|
125
147
|
insert_tramp("read", read_tramp);
|
126
148
|
insert_tramp("write", write_tramp);
|
127
|
-
insert_tramp("
|
149
|
+
insert_tramp("poll", poll_tramp);
|
150
|
+
|
128
151
|
#ifdef HAVE_MACH
|
129
152
|
insert_tramp("select$DARWIN_EXTSN", select_tramp);
|
130
153
|
#else
|
131
154
|
insert_tramp("select", select_tramp);
|
155
|
+
insert_tramp("connect", connect_tramp);
|
132
156
|
#endif
|
133
157
|
}
|
134
158
|
|
@@ -149,7 +173,7 @@ fd_trace_dump(json_gen gen) {
|
|
149
173
|
json_gen_cstr(gen, "calls");
|
150
174
|
json_gen_integer(gen, stats.read_calls);
|
151
175
|
json_gen_cstr(gen, "time");
|
152
|
-
|
176
|
+
json_gen_integer(gen, stats.read_time);
|
153
177
|
json_gen_cstr(gen, "requested");
|
154
178
|
json_gen_integer(gen, stats.read_requested_bytes);
|
155
179
|
json_gen_cstr(gen, "actual");
|
@@ -163,7 +187,7 @@ fd_trace_dump(json_gen gen) {
|
|
163
187
|
json_gen_cstr(gen, "calls");
|
164
188
|
json_gen_integer(gen, stats.write_calls);
|
165
189
|
json_gen_cstr(gen, "time");
|
166
|
-
|
190
|
+
json_gen_integer(gen, stats.write_time);
|
167
191
|
json_gen_cstr(gen, "requested");
|
168
192
|
json_gen_integer(gen, stats.write_requested_bytes);
|
169
193
|
json_gen_cstr(gen, "actual");
|
@@ -177,7 +201,7 @@ fd_trace_dump(json_gen gen) {
|
|
177
201
|
json_gen_cstr(gen, "calls");
|
178
202
|
json_gen_integer(gen, stats.connect_calls);
|
179
203
|
json_gen_cstr(gen, "time");
|
180
|
-
|
204
|
+
json_gen_integer(gen, stats.connect_time);
|
181
205
|
json_gen_map_close(gen);
|
182
206
|
}
|
183
207
|
|
@@ -187,7 +211,17 @@ fd_trace_dump(json_gen gen) {
|
|
187
211
|
json_gen_cstr(gen, "calls");
|
188
212
|
json_gen_integer(gen, stats.select_calls);
|
189
213
|
json_gen_cstr(gen, "time");
|
190
|
-
|
214
|
+
json_gen_integer(gen, stats.select_time);
|
215
|
+
json_gen_map_close(gen);
|
216
|
+
}
|
217
|
+
|
218
|
+
if (stats.poll_calls > 0) {
|
219
|
+
json_gen_cstr(gen, "poll");
|
220
|
+
json_gen_map_open(gen);
|
221
|
+
json_gen_cstr(gen, "calls");
|
222
|
+
json_gen_integer(gen, stats.poll_calls);
|
223
|
+
json_gen_cstr(gen, "time");
|
224
|
+
json_gen_integer(gen, stats.poll_time);
|
191
225
|
json_gen_map_close(gen);
|
192
226
|
}
|
193
227
|
}
|
data/ext/tracers/gc.c
CHANGED
@@ -13,7 +13,7 @@
|
|
13
13
|
|
14
14
|
struct memprof_gc_stats {
|
15
15
|
size_t gc_calls;
|
16
|
-
|
16
|
+
uint32_t gc_time;
|
17
17
|
};
|
18
18
|
|
19
19
|
static struct tracer tracer;
|
@@ -23,13 +23,13 @@ static void (*orig_garbage_collect)();
|
|
23
23
|
static void
|
24
24
|
gc_tramp()
|
25
25
|
{
|
26
|
-
|
26
|
+
uint32_t millis = 0;
|
27
27
|
|
28
|
-
|
28
|
+
millis = timeofday_ms();
|
29
29
|
orig_garbage_collect();
|
30
|
-
|
30
|
+
millis = timeofday_ms() - millis;
|
31
31
|
|
32
|
-
stats.gc_time +=
|
32
|
+
stats.gc_time += millis;
|
33
33
|
stats.gc_calls++;
|
34
34
|
}
|
35
35
|
|
@@ -64,7 +64,7 @@ gc_trace_dump(json_gen gen) {
|
|
64
64
|
json_gen_integer(gen, stats.gc_calls);
|
65
65
|
|
66
66
|
json_gen_cstr(gen, "time");
|
67
|
-
|
67
|
+
json_gen_integer(gen, stats.gc_time);
|
68
68
|
}
|
69
69
|
|
70
70
|
void install_gc_tracer()
|
data/ext/tracers/mysql.c
CHANGED
@@ -9,30 +9,55 @@
|
|
9
9
|
#include "bin_api.h"
|
10
10
|
#include "json.h"
|
11
11
|
#include "tracer.h"
|
12
|
+
#include "tracers/sql.h"
|
12
13
|
#include "tramp.h"
|
13
14
|
#include "util.h"
|
14
15
|
|
15
16
|
struct memprof_mysql_stats {
|
16
17
|
size_t query_calls;
|
17
|
-
|
18
|
+
uint32_t query_time;
|
19
|
+
|
20
|
+
size_t query_calls_by_type[sql_UNKNOWN];
|
21
|
+
uint32_t query_time_by_type[sql_UNKNOWN];
|
18
22
|
};
|
19
23
|
|
20
24
|
static struct tracer tracer;
|
21
25
|
static struct memprof_mysql_stats stats;
|
26
|
+
|
22
27
|
static int (*orig_real_query)(void *mysql, const char *stmt_str, unsigned long length);
|
28
|
+
static int (*orig_send_query)(void *mysql, const char *stmt_str, unsigned long length);
|
23
29
|
|
24
30
|
static int
|
25
31
|
real_query_tramp(void *mysql, const char *stmt_str, unsigned long length) {
|
26
|
-
|
32
|
+
enum memprof_sql_type type;
|
33
|
+
uint32_t millis = 0;
|
27
34
|
int ret;
|
28
35
|
|
29
|
-
|
36
|
+
millis = timeofday_ms();
|
30
37
|
ret = orig_real_query(mysql, stmt_str, length);
|
31
|
-
|
38
|
+
millis = timeofday_ms() - millis;
|
39
|
+
|
40
|
+
stats.query_time += millis;
|
41
|
+
stats.query_calls++;
|
42
|
+
|
43
|
+
type = memprof_sql_query_type(stmt_str, length);
|
44
|
+
stats.query_time_by_type[type] += millis;
|
45
|
+
stats.query_calls_by_type[type]++;
|
46
|
+
|
47
|
+
return ret;
|
48
|
+
}
|
49
|
+
|
50
|
+
static int
|
51
|
+
send_query_tramp(void *mysql, const char *stmt_str, unsigned long length) {
|
52
|
+
enum memprof_sql_type type;
|
53
|
+
int ret;
|
32
54
|
|
33
|
-
|
55
|
+
ret = orig_send_query(mysql, stmt_str, length);
|
34
56
|
stats.query_calls++;
|
35
57
|
|
58
|
+
type = memprof_sql_query_type(stmt_str, length);
|
59
|
+
stats.query_calls_by_type[type]++;
|
60
|
+
|
36
61
|
return ret;
|
37
62
|
}
|
38
63
|
|
@@ -48,6 +73,10 @@ mysql_trace_start() {
|
|
48
73
|
orig_real_query = bin_find_symbol("mysql_real_query", NULL, 1);
|
49
74
|
if (orig_real_query)
|
50
75
|
insert_tramp("mysql_real_query", real_query_tramp);
|
76
|
+
|
77
|
+
orig_send_query = bin_find_symbol("mysql_send_query", NULL, 1);
|
78
|
+
if (orig_send_query)
|
79
|
+
insert_tramp("mysql_send_query", send_query_tramp);
|
51
80
|
}
|
52
81
|
|
53
82
|
static void
|
@@ -61,12 +90,30 @@ mysql_trace_reset() {
|
|
61
90
|
|
62
91
|
static void
|
63
92
|
mysql_trace_dump(json_gen gen) {
|
93
|
+
enum memprof_sql_type i;
|
94
|
+
|
64
95
|
if (stats.query_calls > 0) {
|
65
96
|
json_gen_cstr(gen, "queries");
|
66
97
|
json_gen_integer(gen, stats.query_calls);
|
67
98
|
|
68
99
|
json_gen_cstr(gen, "time");
|
69
|
-
|
100
|
+
json_gen_integer(gen, stats.query_time);
|
101
|
+
|
102
|
+
json_gen_cstr(gen, "types");
|
103
|
+
json_gen_map_open(gen);
|
104
|
+
for (i=0; i<=sql_UNKNOWN; i++) {
|
105
|
+
json_gen_cstr(gen, memprof_sql_type_str(i));
|
106
|
+
json_gen_map_open(gen);
|
107
|
+
|
108
|
+
json_gen_cstr(gen, "queries");
|
109
|
+
json_gen_integer(gen, stats.query_calls_by_type[i]);
|
110
|
+
|
111
|
+
json_gen_cstr(gen, "time");
|
112
|
+
json_gen_integer(gen, stats.query_time_by_type[i]);
|
113
|
+
|
114
|
+
json_gen_map_close(gen);
|
115
|
+
}
|
116
|
+
json_gen_map_close(gen);
|
70
117
|
}
|
71
118
|
}
|
72
119
|
|
data/ext/tracers/postgres.c
CHANGED
@@ -9,11 +9,13 @@
|
|
9
9
|
#include "bin_api.h"
|
10
10
|
#include "json.h"
|
11
11
|
#include "tracer.h"
|
12
|
+
#include "tracers/sql.h"
|
12
13
|
#include "tramp.h"
|
13
14
|
#include "util.h"
|
14
15
|
|
15
16
|
struct memprof_postgres_stats {
|
16
17
|
size_t query_calls;
|
18
|
+
size_t query_calls_by_type[sql_UNKNOWN+1];
|
17
19
|
};
|
18
20
|
|
19
21
|
static struct tracer tracer;
|
@@ -22,11 +24,15 @@ static void * (*orig_PQexec)(void *postgres, const char *stmt);
|
|
22
24
|
|
23
25
|
static void *
|
24
26
|
PQexec_tramp(void *postgres, const char *stmt) {
|
27
|
+
enum memprof_sql_type type;
|
25
28
|
void *ret;
|
26
29
|
|
27
30
|
ret = orig_PQexec(postgres, stmt);
|
28
31
|
stats.query_calls++;
|
29
32
|
|
33
|
+
type = memprof_sql_query_type(stmt, strlen(stmt));
|
34
|
+
stats.query_calls_by_type[type]++;
|
35
|
+
|
30
36
|
return ret;
|
31
37
|
}
|
32
38
|
|
@@ -55,9 +61,22 @@ postgres_trace_reset() {
|
|
55
61
|
|
56
62
|
static void
|
57
63
|
postgres_trace_dump(json_gen gen) {
|
64
|
+
enum memprof_sql_type i;
|
65
|
+
|
58
66
|
if (stats.query_calls > 0) {
|
59
67
|
json_gen_cstr(gen, "queries");
|
60
68
|
json_gen_integer(gen, stats.query_calls);
|
69
|
+
|
70
|
+
json_gen_cstr(gen, "types");
|
71
|
+
json_gen_map_open(gen);
|
72
|
+
for (i=0; i<=sql_UNKNOWN; i++) {
|
73
|
+
json_gen_cstr(gen, memprof_sql_type_str(i));
|
74
|
+
json_gen_map_open(gen);
|
75
|
+
json_gen_cstr(gen, "queries");
|
76
|
+
json_gen_integer(gen, stats.query_calls_by_type[i]);
|
77
|
+
json_gen_map_close(gen);
|
78
|
+
}
|
79
|
+
json_gen_map_close(gen);
|
61
80
|
}
|
62
81
|
}
|
63
82
|
|
data/ext/tracers/resources.c
CHANGED
@@ -15,14 +15,14 @@ struct memprof_resources_stats {
|
|
15
15
|
long inblock;
|
16
16
|
long oublock;
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
int64_t utime;
|
19
|
+
int64_t stime;
|
20
20
|
};
|
21
21
|
|
22
22
|
static struct tracer tracer;
|
23
23
|
static struct memprof_resources_stats stats;
|
24
24
|
|
25
|
-
#define
|
25
|
+
#define TVAL_TO_INT64(tv) ((int64_t)tv.tv_sec*1e3 + (int64_t)tv.tv_usec*1e-3)
|
26
26
|
|
27
27
|
static void
|
28
28
|
resources_trace_start() {
|
@@ -34,8 +34,8 @@ resources_trace_start() {
|
|
34
34
|
stats.inblock = -usage.ru_inblock;
|
35
35
|
stats.oublock = -usage.ru_oublock;
|
36
36
|
|
37
|
-
stats.stime = -
|
38
|
-
stats.utime = -
|
37
|
+
stats.stime = -TVAL_TO_INT64(usage.ru_stime);
|
38
|
+
stats.utime = -TVAL_TO_INT64(usage.ru_utime);
|
39
39
|
}
|
40
40
|
|
41
41
|
static void
|
@@ -49,8 +49,8 @@ resources_trace_dump(json_gen gen) {
|
|
49
49
|
stats.inblock += usage.ru_inblock;
|
50
50
|
stats.oublock += usage.ru_oublock;
|
51
51
|
|
52
|
-
stats.stime +=
|
53
|
-
stats.utime +=
|
52
|
+
stats.stime += TVAL_TO_INT64(usage.ru_stime);
|
53
|
+
stats.utime += TVAL_TO_INT64(usage.ru_utime);
|
54
54
|
}
|
55
55
|
|
56
56
|
json_gen_cstr(gen, "signals");
|
@@ -63,10 +63,10 @@ resources_trace_dump(json_gen gen) {
|
|
63
63
|
json_gen_integer(gen, stats.oublock);
|
64
64
|
|
65
65
|
json_gen_cstr(gen, "stime");
|
66
|
-
|
66
|
+
json_gen_integer(gen, stats.stime);
|
67
67
|
|
68
68
|
json_gen_cstr(gen, "utime");
|
69
|
-
|
69
|
+
json_gen_integer(gen, stats.utime);
|
70
70
|
}
|
71
71
|
|
72
72
|
static void
|
@@ -83,7 +83,7 @@ void install_resources_tracer()
|
|
83
83
|
tracer.stop = resources_trace_stop;
|
84
84
|
tracer.reset = resources_trace_reset;
|
85
85
|
tracer.dump = resources_trace_dump;
|
86
|
-
tracer.id = "
|
86
|
+
tracer.id = "resources";
|
87
87
|
|
88
88
|
trace_insert(&tracer);
|
89
89
|
}
|
data/ext/tracers/sql.c
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
#include <tracers/sql.h>
|
2
|
+
|
3
|
+
enum memprof_sql_type
|
4
|
+
memprof_sql_query_type(const char *stmt, unsigned long length)
|
5
|
+
{
|
6
|
+
int i;
|
7
|
+
|
8
|
+
for (i=0; i<length && i<10; i++) {
|
9
|
+
switch (stmt[i]) {
|
10
|
+
case ' ':
|
11
|
+
case '\n':
|
12
|
+
case '\r':
|
13
|
+
continue;
|
14
|
+
break;
|
15
|
+
|
16
|
+
case 'S':
|
17
|
+
case 's':
|
18
|
+
return sql_SELECT;
|
19
|
+
|
20
|
+
case 'I':
|
21
|
+
case 'i':
|
22
|
+
return sql_INSERT;
|
23
|
+
|
24
|
+
case 'U':
|
25
|
+
case 'u':
|
26
|
+
return sql_UPDATE;
|
27
|
+
|
28
|
+
case 'D':
|
29
|
+
case 'd':
|
30
|
+
return sql_DELETE;
|
31
|
+
|
32
|
+
default:
|
33
|
+
return sql_UNKNOWN;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
return sql_UNKNOWN;
|
38
|
+
}
|
39
|
+
|
40
|
+
const char *
|
41
|
+
memprof_sql_type_str(enum memprof_sql_type type)
|
42
|
+
{
|
43
|
+
switch (type) {
|
44
|
+
case sql_SELECT:
|
45
|
+
return "select";
|
46
|
+
case sql_UPDATE:
|
47
|
+
return "update";
|
48
|
+
case sql_INSERT:
|
49
|
+
return "insert";
|
50
|
+
case sql_DELETE:
|
51
|
+
return "delete";
|
52
|
+
default:
|
53
|
+
case sql_UNKNOWN:
|
54
|
+
return "unknown";
|
55
|
+
}
|
56
|
+
}
|
data/ext/tracers/sql.h
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#if !defined(_sql_h_)
|
2
|
+
#define _sql_h_
|
3
|
+
|
4
|
+
enum memprof_sql_type {
|
5
|
+
sql_SELECT,
|
6
|
+
sql_UPDATE,
|
7
|
+
sql_INSERT,
|
8
|
+
sql_DELETE,
|
9
|
+
sql_UNKNOWN // last
|
10
|
+
};
|
11
|
+
|
12
|
+
enum memprof_sql_type
|
13
|
+
memprof_sql_query_type(const char *stmt, unsigned long length);
|
14
|
+
|
15
|
+
const char *
|
16
|
+
memprof_sql_type_str(enum memprof_sql_type);
|
17
|
+
|
18
|
+
#endif
|
data/ext/util.c
CHANGED
@@ -89,3 +89,11 @@ timeofday()
|
|
89
89
|
gettimeofday(&tv, NULL);
|
90
90
|
return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
|
91
91
|
}
|
92
|
+
|
93
|
+
uint64_t
|
94
|
+
timeofday_ms()
|
95
|
+
{
|
96
|
+
struct timeval tv;
|
97
|
+
gettimeofday(&tv, NULL);
|
98
|
+
return (uint64_t)tv.tv_sec*1e3 + (uint64_t)tv.tv_usec*1e-3;
|
99
|
+
}
|
data/ext/util.h
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
#if !defined(__util_h__)
|
2
2
|
#define __util_h__
|
3
3
|
|
4
|
+
#include <stdint.h>
|
5
|
+
|
4
6
|
#if defined(_MEMPROF_DEBUG)
|
5
7
|
#include <stdio.h>
|
6
8
|
#define dbg_printf(...) do {\
|
@@ -73,9 +75,13 @@ struct memprof_config {
|
|
73
75
|
unsigned long
|
74
76
|
gnu_debuglink_crc32 (unsigned long crc, unsigned char *buf, size_t len);
|
75
77
|
|
78
|
+
/* Copy of timeofday() implementation inside ruby 1.8, used w/ thread state */
|
79
|
+
double
|
80
|
+
timeofday();
|
81
|
+
|
76
82
|
/* Use this function for time tracking. It will (interally) try to use an
|
77
83
|
* appropriately granual timing function.
|
78
84
|
*/
|
79
|
-
|
80
|
-
|
85
|
+
uint64_t
|
86
|
+
timeofday_ms();
|
81
87
|
#endif
|
data/memprof.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
spec = Gem::Specification.new do |s|
|
2
2
|
s.name = 'memprof'
|
3
|
-
s.version = '0.3.
|
3
|
+
s.version = '0.3.8'
|
4
4
|
s.summary = 'Ruby Memory Profiler'
|
5
5
|
s.description = "Ruby memory profiler similar to bleak_house, but without patches to the Ruby VM"
|
6
6
|
s.homepage = "http://github.com/ice799/memprof"
|
data/spec/tracing_spec.rb
CHANGED
@@ -38,9 +38,9 @@ describe 'Memprof tracers' do
|
|
38
38
|
select(nil, nil, nil, 0.15)
|
39
39
|
end
|
40
40
|
|
41
|
-
filedata.should =~ /"select":\{"calls":1,"time":
|
41
|
+
filedata.should =~ /"select":\{"calls":1,"time":1[567]\d/
|
42
42
|
time = filedata[/"select":\{"calls":\d+,"time":([\d.]+)/, 1].to_f
|
43
|
-
time.should.be.close(
|
43
|
+
time.should.be.close(150, 10)
|
44
44
|
end
|
45
45
|
|
46
46
|
should 'trace objects created for block' do
|
@@ -79,7 +79,7 @@ describe 'Memprof tracers' do
|
|
79
79
|
|
80
80
|
filedata.should =~ /"mysql":\{"queries":5,"time":([\d.]+)/
|
81
81
|
time = filedata[/"mysql":\{"queries":5,"time":([\d.]+)/, 1].to_f
|
82
|
-
time.should.be.close(
|
82
|
+
time.should.be.close(250, 25)
|
83
83
|
end
|
84
84
|
rescue Mysql::Error => e
|
85
85
|
raise unless e.message =~ /connect/
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: memprof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
9
|
+
- 8
|
10
|
+
version: 0.3.8
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Joe Damato
|
@@ -18,7 +18,7 @@ autorequire:
|
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
20
|
|
21
|
-
date: 2011-01-
|
21
|
+
date: 2011-01-31 00:00:00 -08:00
|
22
22
|
default_executable:
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
@@ -91,6 +91,8 @@ files:
|
|
91
91
|
- ext/tracers/objects.c
|
92
92
|
- ext/tracers/postgres.c
|
93
93
|
- ext/tracers/resources.c
|
94
|
+
- ext/tracers/sql.c
|
95
|
+
- ext/tracers/sql.h
|
94
96
|
- ext/tramp.c
|
95
97
|
- ext/tramp.h
|
96
98
|
- ext/util.c
|