memprof 0.3.7 → 0.3.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|