memprof 0.3.2 → 0.3.3

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.
@@ -0,0 +1,202 @@
1
+ #include <assert.h>
2
+ #include <errno.h>
3
+ #include <stdio.h>
4
+ #include <stdlib.h>
5
+ #include <string.h>
6
+
7
+ #include "arch.h"
8
+ #include "bin_api.h"
9
+ #include "json.h"
10
+ #include "tracer.h"
11
+ #include "tramp.h"
12
+ #include "util.h"
13
+
14
+ struct memprof_memory_stats {
15
+ size_t malloc_bytes_requested;
16
+ size_t calloc_bytes_requested;
17
+ size_t realloc_bytes_requested;
18
+
19
+ size_t malloc_bytes_actual;
20
+ size_t calloc_bytes_actual;
21
+ size_t realloc_bytes_actual;
22
+ size_t free_bytes_actual;
23
+
24
+ size_t malloc_calls;
25
+ size_t calloc_calls;
26
+ size_t realloc_calls;
27
+ size_t free_calls;
28
+ };
29
+
30
+ static struct tracer tracer;
31
+ static struct memprof_memory_stats stats;
32
+ static size_t (*malloc_usable_size)(void *ptr);
33
+
34
+ static void *
35
+ malloc_tramp(size_t size)
36
+ {
37
+ void *ret = NULL;
38
+ int err;
39
+
40
+ ret = malloc(size);
41
+ err = errno;
42
+
43
+ stats.malloc_bytes_requested += size;
44
+ stats.malloc_calls++;
45
+
46
+ if (ret)
47
+ stats.malloc_bytes_actual += malloc_usable_size(ret);
48
+
49
+ errno = err;
50
+ return ret;
51
+ }
52
+
53
+ static void *
54
+ calloc_tramp(size_t nmemb, size_t size)
55
+ {
56
+ void *ret = NULL;
57
+ int err;
58
+
59
+ ret = calloc(nmemb, size);
60
+ err = errno;
61
+
62
+ stats.calloc_bytes_requested += (nmemb * size);
63
+ stats.calloc_calls++;
64
+
65
+ if (ret)
66
+ stats.calloc_bytes_actual += malloc_usable_size(ret);
67
+
68
+ errno = err;
69
+ return ret;
70
+ }
71
+
72
+ static void *
73
+ realloc_tramp(void *ptr, size_t size)
74
+ {
75
+ void *ret = NULL;
76
+ int err;
77
+
78
+ ret = realloc(ptr, size);
79
+ err = errno;
80
+
81
+ stats.realloc_bytes_requested += size;
82
+ stats.realloc_calls++;
83
+
84
+ if (ret)
85
+ stats.realloc_bytes_actual += malloc_usable_size(ret);
86
+
87
+ errno = err;
88
+ return ret;
89
+ }
90
+
91
+ static void
92
+ free_tramp(void *ptr)
93
+ {
94
+ if (ptr)
95
+ stats.free_bytes_actual += malloc_usable_size(ptr);
96
+
97
+ stats.free_calls++;
98
+
99
+ free(ptr);
100
+ }
101
+
102
+ static void
103
+ malloc_trace_start()
104
+ {
105
+ static int inserted = 0;
106
+
107
+ if (!inserted)
108
+ inserted = 1;
109
+ else
110
+ return;
111
+
112
+ if (!malloc_usable_size) {
113
+ malloc_usable_size = bin_find_symbol("MallocExtension_GetAllocatedSize", NULL, 1);
114
+ if (!malloc_usable_size) {
115
+ dbg_printf("tcmalloc was not found...\n");
116
+ malloc_usable_size = bin_find_symbol("malloc_usable_size", NULL, 1);
117
+ }
118
+ if (!malloc_usable_size) {
119
+ dbg_printf("malloc_usable_size was not found...\n");
120
+ malloc_usable_size = bin_find_symbol("malloc_size", NULL, 1);
121
+ }
122
+ assert(malloc_usable_size != NULL);
123
+ dbg_printf("malloc_usable_size: %p\n", malloc_usable_size);
124
+ }
125
+
126
+ insert_tramp("malloc", malloc_tramp);
127
+ insert_tramp("realloc", realloc_tramp);
128
+ insert_tramp("calloc", calloc_tramp);
129
+ insert_tramp("free", free_tramp);
130
+ }
131
+
132
+ static void
133
+ malloc_trace_stop()
134
+ {
135
+ }
136
+
137
+ static void
138
+ malloc_trace_reset()
139
+ {
140
+ memset(&stats, 0, sizeof(stats));
141
+ }
142
+
143
+ static void
144
+ malloc_trace_dump(json_gen gen)
145
+ {
146
+ if (stats.malloc_calls > 0) {
147
+ json_gen_cstr(gen, "malloc");
148
+ json_gen_map_open(gen);
149
+ json_gen_cstr(gen, "calls");
150
+ json_gen_integer(gen, stats.malloc_calls);
151
+ json_gen_cstr(gen, "requested");
152
+ json_gen_integer(gen, stats.malloc_bytes_requested);
153
+ json_gen_cstr(gen, "actual");
154
+ json_gen_integer(gen, stats.malloc_bytes_actual);
155
+ json_gen_map_close(gen);
156
+ }
157
+
158
+ if (stats.realloc_calls > 0) {
159
+ json_gen_cstr(gen, "realloc");
160
+ json_gen_map_open(gen);
161
+ json_gen_cstr(gen, "calls");
162
+ json_gen_integer(gen, stats.realloc_calls);
163
+ json_gen_cstr(gen, "requested");
164
+ json_gen_integer(gen, stats.realloc_bytes_requested);
165
+ json_gen_cstr(gen, "actual");
166
+ json_gen_integer(gen, stats.realloc_bytes_actual);
167
+ json_gen_map_close(gen);
168
+ }
169
+
170
+ if (stats.calloc_calls > 0) {
171
+ json_gen_cstr(gen, "calloc");
172
+ json_gen_map_open(gen);
173
+ json_gen_cstr(gen, "calls");
174
+ json_gen_integer(gen, stats.calloc_calls);
175
+ json_gen_cstr(gen, "requested");
176
+ json_gen_integer(gen, stats.calloc_bytes_requested);
177
+ json_gen_cstr(gen, "actual");
178
+ json_gen_integer(gen, stats.calloc_bytes_actual);
179
+ json_gen_map_close(gen);
180
+ }
181
+
182
+ if (stats.free_calls > 0) {
183
+ json_gen_cstr(gen, "free");
184
+ json_gen_map_open(gen);
185
+ json_gen_cstr(gen, "calls");
186
+ json_gen_integer(gen, stats.free_calls);
187
+ json_gen_cstr(gen, "actual");
188
+ json_gen_integer(gen, stats.free_bytes_actual);
189
+ json_gen_map_close(gen);
190
+ }
191
+ }
192
+
193
+ void install_malloc_tracer()
194
+ {
195
+ tracer.start = malloc_trace_start;
196
+ tracer.stop = malloc_trace_stop;
197
+ tracer.reset = malloc_trace_reset;
198
+ tracer.dump = malloc_trace_dump;
199
+ tracer.id = "memory";
200
+
201
+ trace_insert(&tracer);
202
+ }
@@ -0,0 +1,82 @@
1
+ #include <assert.h>
2
+ #include <errno.h>
3
+ #include <stdio.h>
4
+ #include <stdlib.h>
5
+ #include <string.h>
6
+ #include <sys/time.h>
7
+
8
+ #include "arch.h"
9
+ #include "bin_api.h"
10
+ #include "json.h"
11
+ #include "tracer.h"
12
+ #include "tramp.h"
13
+ #include "util.h"
14
+
15
+ struct memprof_mysql_stats {
16
+ size_t query_calls;
17
+ double query_time;
18
+ };
19
+
20
+ static struct tracer tracer;
21
+ static struct memprof_mysql_stats stats;
22
+ static int (*orig_real_query)(void *mysql, const char *stmt_str, unsigned long length);
23
+
24
+ static int
25
+ real_query_tramp(void *mysql, const char *stmt_str, unsigned long length) {
26
+ double secs = 0;
27
+ int ret;
28
+
29
+ secs = timeofday();
30
+ ret = orig_real_query(mysql, stmt_str, length);
31
+ secs = timeofday() - secs;
32
+
33
+ stats.query_time += secs;
34
+ stats.query_calls++;
35
+
36
+ return ret;
37
+ }
38
+
39
+ static void
40
+ mysql_trace_start() {
41
+ static int inserted = 0;
42
+
43
+ if (!inserted)
44
+ inserted = 1;
45
+ else
46
+ return;
47
+
48
+ orig_real_query = bin_find_symbol("mysql_real_query", NULL, 1);
49
+ if (orig_real_query)
50
+ insert_tramp("mysql_real_query", real_query_tramp);
51
+ }
52
+
53
+ static void
54
+ mysql_trace_stop() {
55
+ }
56
+
57
+ static void
58
+ mysql_trace_reset() {
59
+ memset(&stats, 0, sizeof(stats));
60
+ }
61
+
62
+ static void
63
+ mysql_trace_dump(json_gen gen) {
64
+ if (stats.query_calls > 0) {
65
+ json_gen_cstr(gen, "queries");
66
+ json_gen_integer(gen, stats.query_calls);
67
+
68
+ json_gen_cstr(gen, "time");
69
+ json_gen_double(gen, stats.query_time);
70
+ }
71
+ }
72
+
73
+ void install_mysql_tracer()
74
+ {
75
+ tracer.start = mysql_trace_start;
76
+ tracer.stop = mysql_trace_stop;
77
+ tracer.reset = mysql_trace_reset;
78
+ tracer.dump = mysql_trace_dump;
79
+ tracer.id = "mysql";
80
+
81
+ trace_insert(&tracer);
82
+ }
@@ -0,0 +1,160 @@
1
+ #include <assert.h>
2
+ #include <stdio.h>
3
+ #include <stdlib.h>
4
+ #include <string.h>
5
+
6
+ #include "arch.h"
7
+ #include "bin_api.h"
8
+ #include "json.h"
9
+ #include "tracer.h"
10
+ #include "tramp.h"
11
+ #include "util.h"
12
+ #include "ruby.h"
13
+
14
+ struct memprof_objects_stats {
15
+ size_t newobj_calls;
16
+ size_t types[T_MASK+1];
17
+ };
18
+
19
+ static struct tracer tracer;
20
+ static struct memprof_objects_stats stats;
21
+ static VALUE (*orig_rb_newobj)();
22
+
23
+ static VALUE last_obj = 0;
24
+ static VALUE gc_hook = 0;
25
+
26
+ static void
27
+ record_last_obj()
28
+ {
29
+ if (last_obj) {
30
+ stats.types[BUILTIN_TYPE(last_obj)]++;
31
+ last_obj = 0;
32
+ }
33
+ }
34
+
35
+ static VALUE
36
+ objects_tramp() {
37
+ record_last_obj();
38
+ stats.newobj_calls++;
39
+ last_obj = orig_rb_newobj();
40
+ return last_obj;
41
+ }
42
+
43
+ static void
44
+ objects_trace_start() {
45
+ static int inserted = 0;
46
+
47
+ if (!inserted)
48
+ inserted = 1;
49
+ else
50
+ return;
51
+
52
+ orig_rb_newobj = bin_find_symbol("rb_newobj", NULL, 0);
53
+ assert(orig_rb_newobj != NULL);
54
+ dbg_printf("orig_rb_newobj: %p\n", orig_rb_newobj);
55
+
56
+ insert_tramp("rb_newobj", objects_tramp);
57
+ }
58
+
59
+ static void
60
+ objects_trace_stop() {
61
+ }
62
+
63
+ static void
64
+ objects_trace_reset() {
65
+ memset(&stats, 0, sizeof(stats));
66
+ last_obj = 0;
67
+ }
68
+
69
+ static inline char*
70
+ type_string(int type) {
71
+ switch (type) {
72
+ case T_NONE:
73
+ return "none";
74
+ case T_NIL:
75
+ return "nil";
76
+ case T_OBJECT:
77
+ return "object";
78
+ case T_CLASS:
79
+ return "class";
80
+ case T_ICLASS:
81
+ return "iclass";
82
+ case T_MODULE:
83
+ return "module";
84
+ case T_FLOAT:
85
+ return "float";
86
+ case T_STRING:
87
+ return "string";
88
+ case T_REGEXP:
89
+ return "regexp";
90
+ case T_ARRAY:
91
+ return "array";
92
+ case T_FIXNUM:
93
+ return "fixnum";
94
+ case T_HASH:
95
+ return "hash";
96
+ case T_STRUCT:
97
+ return "struct";
98
+ case T_BIGNUM:
99
+ return "bignum";
100
+ case T_FILE:
101
+ return "file";
102
+ case T_TRUE:
103
+ return "true";
104
+ case T_FALSE:
105
+ return "false";
106
+ case T_DATA:
107
+ return "data";
108
+ case T_MATCH:
109
+ return "match";
110
+ case T_SYMBOL:
111
+ return "symbol";
112
+ case T_BLKTAG:
113
+ return "blktag";
114
+ case T_UNDEF:
115
+ return "undef";
116
+ case T_VARMAP:
117
+ return "varmap";
118
+ case T_SCOPE:
119
+ return "scope";
120
+ case T_NODE:
121
+ return "node";
122
+ default:
123
+ return "unknown";
124
+ }
125
+ }
126
+
127
+ static void
128
+ objects_trace_dump(json_gen gen) {
129
+ int i;
130
+ record_last_obj();
131
+
132
+ json_gen_cstr(gen, "created");
133
+ json_gen_integer(gen, stats.newobj_calls);
134
+
135
+ json_gen_cstr(gen, "types");
136
+ json_gen_map_open(gen);
137
+ for (i=0; i<T_MASK+1; i++) {
138
+ if (stats.types[i] > 0) {
139
+ json_gen_cstr(gen, type_string(i));
140
+ json_gen_integer(gen, stats.types[i]);
141
+ }
142
+ }
143
+ json_gen_map_close(gen);
144
+ }
145
+
146
+ void install_objects_tracer()
147
+ {
148
+ if (!gc_hook) {
149
+ gc_hook = Data_Wrap_Struct(rb_cObject, record_last_obj, NULL, NULL);
150
+ rb_global_variable(&gc_hook);
151
+ }
152
+
153
+ tracer.start = objects_trace_start;
154
+ tracer.stop = objects_trace_stop;
155
+ tracer.reset = objects_trace_reset;
156
+ tracer.dump = objects_trace_dump;
157
+ tracer.id = "objects";
158
+
159
+ trace_insert(&tracer);
160
+ }
@@ -107,7 +107,7 @@ hook_freelist(int entry, void *tramp)
107
107
  }
108
108
 
109
109
  /* if we've looked at all the bytes in this function... */
110
- if (((void *)byte - freelist_inliners[i]) >= sizes[i]) {
110
+ if ((size_t)((void *)byte - freelist_inliners[i]) >= sizes[i]) {
111
111
  /* move on to the next function */
112
112
  i++;
113
113
  byte = freelist_inliners[i];
@@ -123,7 +123,7 @@ hook_freelist(int entry, void *tramp)
123
123
  void
124
124
  insert_tramp(const char *trampee, void *tramp)
125
125
  {
126
- void *trampee_addr = bin_find_symbol(trampee, NULL, 0);
126
+ void *trampee_addr = bin_find_symbol(trampee, NULL, 1);
127
127
  int inline_ent = inline_tramp_size;
128
128
 
129
129
  if (trampee_addr == NULL) {