memprof 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,73 @@
1
+ /*
2
+ * Following code taken from http://thebends.googlecode.com/svn/trunk/mach-o/mmap.c
3
+ * Copyright: Allen Porter <allen@thebends.org>
4
+ */
5
+ #ifndef __MMAP_H__
6
+ #define __MMAP_H__
7
+
8
+ #include <assert.h>
9
+ #include <errno.h>
10
+ #include <fcntl.h>
11
+ #include <mach/vm_param.h>
12
+ #include <stdlib.h>
13
+ #include <stdio.h>
14
+ #include <sys/stat.h>
15
+ #include <sys/mman.h>
16
+ #include <unistd.h>
17
+
18
+ /*
19
+ * Simple utililty methods for mmaping files.
20
+ */
21
+
22
+ struct mmap_info {
23
+ const char *name; /* filename */
24
+ int fd; /* file descriptor */
25
+ size_t data_size; /* size of file */
26
+ void* data; /* mmap'd writable contents of file */
27
+ };
28
+
29
+ /*
30
+ * Open a file, memory map its contents, and populate mmap_info. Requires a
31
+ * filename.
32
+ */
33
+ int mmap_file_open(struct mmap_info *file_info) {
34
+ assert(file_info != NULL);
35
+ file_info->fd = open(file_info->name, O_RDONLY);
36
+ if (file_info->fd < 0) {
37
+ perror("open");
38
+ return -1;
39
+ }
40
+ struct stat sb;
41
+ if (fstat(file_info->fd, &sb) < 0) {
42
+ perror("fstat");
43
+ return -1;
44
+ }
45
+ file_info->data_size = (size_t)sb.st_size;
46
+ size_t map_size = file_info->data_size;
47
+ file_info->data = mmap(0, map_size,
48
+ PROT_READ,
49
+ MAP_FILE | MAP_SHARED,
50
+ file_info->fd, /* offset */0);
51
+ if (file_info->data == MAP_FAILED) {
52
+ perror("mmap");
53
+ return -1;
54
+ }
55
+ return 0;
56
+ }
57
+
58
+ /*
59
+ * Unmemory map and close the file in file_info.
60
+ */
61
+ int munmap_file(struct mmap_info *file_info) {
62
+ if (munmap(file_info->data, file_info->data_size) < 0) {
63
+ perror("munmap");
64
+ return -1;
65
+ }
66
+ if (close(file_info->fd) < 0) {
67
+ perror("close");
68
+ return -1;
69
+ }
70
+ return 0;
71
+ }
72
+
73
+ #endif /* __MMAP_H__ */
@@ -1,10 +1,14 @@
1
1
  #include <assert.h>
2
+ #include <stdio.h>
2
3
  #include <stdlib.h>
3
4
  #include <string.h>
4
5
 
6
+ #include "json.h"
5
7
  #include "tracer.h"
6
8
  #include "util.h"
7
9
 
10
+ static json_gen tracing_json_gen = NULL;
11
+
8
12
  /*
9
13
  XXX if we ever need a linked list for anything else ever, remove this crap
10
14
  and switch to a generic macro-based linked list implementation
@@ -38,7 +42,6 @@ trace_remove(const char *id)
38
42
  while (tmp) {
39
43
  if (strcmp(id, tmp->tracer->id) == 0) {
40
44
  tmp->next = tmp->next;
41
- free(tmp->tracer->id);
42
45
  free(tmp->tracer);
43
46
  free(tmp);
44
47
  return 0;
@@ -64,7 +67,10 @@ do_trace_invoke(struct tracer *trace, trace_fn fn)
64
67
  trace->reset();
65
68
  break;
66
69
  case TRACE_DUMP:
67
- trace->dump();
70
+ json_gen_cstr(tracing_json_gen, trace->id);
71
+ json_gen_map_open(tracing_json_gen);
72
+ trace->dump(tracing_json_gen);
73
+ json_gen_map_close(tracing_json_gen);
68
74
  break;
69
75
  default:
70
76
  dbg_printf("invoked a non-existant trace function type: %d", fn);
@@ -97,3 +103,15 @@ trace_invoke(const char *id, trace_fn fn)
97
103
  }
98
104
  return 0;
99
105
  }
106
+
107
+ void
108
+ trace_set_output(json_gen gen)
109
+ {
110
+ tracing_json_gen = gen;
111
+ }
112
+
113
+ json_gen
114
+ trace_get_output()
115
+ {
116
+ return tracing_json_gen;
117
+ }
@@ -1,12 +1,14 @@
1
1
  #if !defined(__TRACER__H_)
2
2
  #define __TRACER__H_
3
3
 
4
+ #include "json.h"
5
+
4
6
  struct tracer {
5
7
  char *id;
6
8
  void (*start)();
7
9
  void (*stop)();
8
10
  void (*reset)();
9
- void (*dump)();
11
+ void (*dump)(json_gen);
10
12
  };
11
13
 
12
14
  typedef enum {
@@ -28,6 +30,17 @@ trace_invoke_all(trace_fn fn);
28
30
  int
29
31
  trace_invoke(const char *id, trace_fn fn);
30
32
 
33
+ void
34
+ trace_set_output(json_gen gen);
35
+
36
+ json_gen
37
+ trace_get_output();
38
+
31
39
  /* for now, these will live here */
32
40
  extern void install_malloc_tracer();
41
+ extern void install_gc_tracer();
42
+ extern void install_fd_tracer();
43
+ extern void install_mysql_tracer();
44
+ extern void install_objects_tracer();
45
+ extern void install_memcache_tracer();
33
46
  #endif
@@ -0,0 +1,204 @@
1
+ #include <assert.h>
2
+ #include <errno.h>
3
+ #include <stdio.h>
4
+ #include <stdlib.h>
5
+ #include <string.h>
6
+ #include <sys/select.h>
7
+ #include <sys/socket.h>
8
+ #include <sys/time.h>
9
+ #include <unistd.h>
10
+
11
+ #include "arch.h"
12
+ #include "bin_api.h"
13
+ #include "json.h"
14
+ #include "tracer.h"
15
+ #include "tramp.h"
16
+ #include "util.h"
17
+
18
+ struct memprof_fd_stats {
19
+ size_t read_calls;
20
+ double read_time;
21
+ size_t read_requested_bytes;
22
+ size_t read_actual_bytes;
23
+
24
+ size_t write_calls;
25
+ double write_time;
26
+ size_t write_requested_bytes;
27
+ size_t write_actual_bytes;
28
+
29
+ size_t connect_calls;
30
+ double connect_time;
31
+
32
+ size_t select_calls;
33
+ double select_time;
34
+ };
35
+
36
+ static struct tracer tracer;
37
+ static struct memprof_fd_stats stats;
38
+
39
+ static ssize_t
40
+ read_tramp(int fildes, void *buf, size_t nbyte) {
41
+ double secs = 0;
42
+ int err;
43
+ ssize_t ret;
44
+
45
+ secs = timeofday();
46
+ ret = read(fildes, buf, nbyte);
47
+ err = errno;
48
+ secs = timeofday() - secs;
49
+
50
+ stats.read_time += secs;
51
+ stats.read_calls++;
52
+ stats.read_requested_bytes += nbyte;
53
+ if (ret > 0)
54
+ stats.read_actual_bytes += ret;
55
+
56
+ errno = err;
57
+ return ret;
58
+ }
59
+
60
+ static ssize_t
61
+ write_tramp(int fildes, const void *buf, size_t nbyte) {
62
+ double secs = 0;
63
+ int err;
64
+ ssize_t ret;
65
+
66
+ secs = timeofday();
67
+ ret = write(fildes, buf, nbyte);
68
+ err = errno;
69
+ secs = timeofday() - secs;
70
+
71
+ stats.write_time += secs;
72
+ stats.write_calls++;
73
+ stats.write_requested_bytes += nbyte;
74
+ if (ret > 0)
75
+ stats.write_actual_bytes += ret;
76
+
77
+ errno = err;
78
+ return ret;
79
+ }
80
+
81
+ static int
82
+ connect_tramp(int socket, const struct sockaddr *address, socklen_t address_len) {
83
+ double secs = 0;
84
+ int err, ret;
85
+
86
+ secs = timeofday();
87
+ ret = connect(socket, address, address_len);
88
+ err = errno;
89
+ secs = timeofday() - secs;
90
+
91
+ stats.connect_time += secs;
92
+ stats.connect_calls++;
93
+
94
+ errno = err;
95
+ return ret;
96
+ }
97
+
98
+ static int
99
+ select_tramp(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)
100
+ {
101
+ double secs = 0;
102
+ int ret, err;
103
+
104
+ secs = timeofday();
105
+ ret = select(nfds, readfds, writefds, errorfds, timeout);
106
+ err = errno;
107
+ secs = timeofday() - secs;
108
+
109
+ stats.select_time += secs;
110
+ stats.select_calls++;
111
+
112
+ errno = err;
113
+ return ret;
114
+ }
115
+
116
+ static void
117
+ fd_trace_start() {
118
+ static int inserted = 0;
119
+
120
+ if (!inserted)
121
+ inserted = 1;
122
+ else
123
+ return;
124
+
125
+ insert_tramp("read", read_tramp);
126
+ insert_tramp("write", write_tramp);
127
+ insert_tramp("connect", connect_tramp);
128
+ #ifdef HAVE_MACH
129
+ insert_tramp("select$DARWIN_EXTSN", select_tramp);
130
+ #else
131
+ insert_tramp("select", select_tramp);
132
+ #endif
133
+ }
134
+
135
+ static void
136
+ fd_trace_stop() {
137
+ }
138
+
139
+ static void
140
+ fd_trace_reset() {
141
+ memset(&stats, 0, sizeof(stats));
142
+ }
143
+
144
+ static void
145
+ fd_trace_dump(json_gen gen) {
146
+ if (stats.read_calls > 0) {
147
+ json_gen_cstr(gen, "read");
148
+ json_gen_map_open(gen);
149
+ json_gen_cstr(gen, "calls");
150
+ json_gen_integer(gen, stats.read_calls);
151
+ json_gen_cstr(gen, "time");
152
+ json_gen_double(gen, stats.read_time);
153
+ json_gen_cstr(gen, "requested");
154
+ json_gen_integer(gen, stats.read_requested_bytes);
155
+ json_gen_cstr(gen, "actual");
156
+ json_gen_integer(gen, stats.read_actual_bytes);
157
+ json_gen_map_close(gen);
158
+ }
159
+
160
+ if (stats.write_calls > 0) {
161
+ json_gen_cstr(gen, "write");
162
+ json_gen_map_open(gen);
163
+ json_gen_cstr(gen, "calls");
164
+ json_gen_integer(gen, stats.write_calls);
165
+ json_gen_cstr(gen, "time");
166
+ json_gen_double(gen, stats.write_time);
167
+ json_gen_cstr(gen, "requested");
168
+ json_gen_integer(gen, stats.write_requested_bytes);
169
+ json_gen_cstr(gen, "actual");
170
+ json_gen_integer(gen, stats.write_actual_bytes);
171
+ json_gen_map_close(gen);
172
+ }
173
+
174
+ if (stats.connect_calls > 0) {
175
+ json_gen_cstr(gen, "connect");
176
+ json_gen_map_open(gen);
177
+ json_gen_cstr(gen, "calls");
178
+ json_gen_integer(gen, stats.connect_calls);
179
+ json_gen_cstr(gen, "time");
180
+ json_gen_double(gen, stats.connect_time);
181
+ json_gen_map_close(gen);
182
+ }
183
+
184
+ if (stats.select_calls > 0) {
185
+ json_gen_cstr(gen, "select");
186
+ json_gen_map_open(gen);
187
+ json_gen_cstr(gen, "calls");
188
+ json_gen_integer(gen, stats.select_calls);
189
+ json_gen_cstr(gen, "time");
190
+ json_gen_double(gen, stats.select_time);
191
+ json_gen_map_close(gen);
192
+ }
193
+ }
194
+
195
+ void install_fd_tracer()
196
+ {
197
+ tracer.start = fd_trace_start;
198
+ tracer.stop = fd_trace_stop;
199
+ tracer.reset = fd_trace_reset;
200
+ tracer.dump = fd_trace_dump;
201
+ tracer.id = "fd";
202
+
203
+ trace_insert(&tracer);
204
+ }
@@ -0,0 +1,79 @@
1
+ #include <assert.h>
2
+ #include <stdio.h>
3
+ #include <stdlib.h>
4
+ #include <string.h>
5
+ #include <sys/time.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_gc_stats {
15
+ size_t gc_calls;
16
+ double gc_time;
17
+ };
18
+
19
+ static struct tracer tracer;
20
+ static struct memprof_gc_stats stats;
21
+ static void (*orig_garbage_collect)();
22
+
23
+ static void
24
+ gc_tramp()
25
+ {
26
+ double secs = 0;
27
+
28
+ secs = timeofday();
29
+ orig_garbage_collect();
30
+ secs = timeofday() - secs;
31
+
32
+ stats.gc_time += secs;
33
+ stats.gc_calls++;
34
+ }
35
+
36
+ static void
37
+ gc_trace_start() {
38
+ static int inserted = 0;
39
+
40
+ if (!inserted)
41
+ inserted = 1;
42
+ else
43
+ return;
44
+
45
+ orig_garbage_collect = bin_find_symbol("garbage_collect", NULL, 0);
46
+ assert(orig_garbage_collect != NULL);
47
+ dbg_printf("orig_garbage_collect: %p\n", orig_garbage_collect);
48
+
49
+ insert_tramp("garbage_collect", gc_tramp);
50
+ }
51
+
52
+ static void
53
+ gc_trace_stop() {
54
+ }
55
+
56
+ static void
57
+ gc_trace_reset() {
58
+ memset(&stats, 0, sizeof(stats));
59
+ }
60
+
61
+ static void
62
+ gc_trace_dump(json_gen gen) {
63
+ json_gen_cstr(gen, "calls");
64
+ json_gen_integer(gen, stats.gc_calls);
65
+
66
+ json_gen_cstr(gen, "time");
67
+ json_gen_double(gen, stats.gc_time);
68
+ }
69
+
70
+ void install_gc_tracer()
71
+ {
72
+ tracer.start = gc_trace_start;
73
+ tracer.stop = gc_trace_stop;
74
+ tracer.reset = gc_trace_reset;
75
+ tracer.dump = gc_trace_dump;
76
+ tracer.id = "gc";
77
+
78
+ trace_insert(&tracer);
79
+ }
@@ -0,0 +1,136 @@
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_memcache_stats {
16
+ size_t get_calls;
17
+ size_t get_responses[45];
18
+
19
+ size_t set_calls;
20
+ size_t set_responses[45];
21
+ };
22
+
23
+ static struct tracer tracer;
24
+ static struct memprof_memcache_stats stats;
25
+ static const char* (*_memcached_lib_version)(void);
26
+ static char* (*_memcached_get)(void *ptr, const char *key, size_t key_length, size_t *value_length, uint32_t *flags, void *error);
27
+ static int (*_memcached_set)(void *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags);
28
+
29
+ static char*
30
+ memcached_get_tramp(void *ptr, const char *key, size_t key_length, size_t *value_length, uint32_t *flags, void *error)
31
+ {
32
+ char* ret = _memcached_get(ptr, key, key_length, value_length, flags, error);
33
+ stats.get_calls++;
34
+ int err = *(int*)error;
35
+ stats.get_responses[err > 42 ? 44 : err]++;
36
+ return ret;
37
+ }
38
+
39
+ static int
40
+ memcached_set_tramp(void *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags)
41
+ {
42
+ int ret = _memcached_set(ptr, key, key_length, value, value_length, expiration, flags);
43
+ stats.set_calls++;
44
+ stats.set_responses[ret > 42 ? 44 : ret]++;
45
+ return ret;
46
+ }
47
+
48
+ static void
49
+ memcache_trace_start() {
50
+ static int inserted = 0;
51
+
52
+ if (!inserted)
53
+ inserted = 1;
54
+ else
55
+ return;
56
+
57
+ _memcached_lib_version = bin_find_symbol("memcached_lib_version", NULL, 1);
58
+ if (_memcached_lib_version) {
59
+ const char *version = _memcached_lib_version();
60
+ if (strcmp(version, "0.32") == 0) {
61
+ _memcached_get = bin_find_symbol("memcached_get", NULL, 1);
62
+ insert_tramp("memcached_get", memcached_get_tramp);
63
+
64
+ _memcached_set = bin_find_symbol("memcached_set", NULL, 1);
65
+ insert_tramp("memcached_set", memcached_set_tramp);
66
+ }
67
+ }
68
+ }
69
+
70
+ static void
71
+ memcache_trace_stop() {
72
+ }
73
+
74
+ static void
75
+ memcache_trace_reset() {
76
+ memset(&stats, 0, sizeof(stats));
77
+ }
78
+
79
+ static void
80
+ memcache_trace_dump_results(json_gen gen, size_t responses[])
81
+ {
82
+ int i;
83
+ json_gen_cstr(gen, "responses");
84
+ json_gen_map_open(gen);
85
+ for (i=0; i < 45; i++) {
86
+ if (responses[i]) {
87
+ switch (i) {
88
+ case 0:
89
+ json_gen_cstr(gen, "success");
90
+ break;
91
+ case 16:
92
+ json_gen_cstr(gen, "notfound");
93
+ break;
94
+ case 44:
95
+ json_gen_cstr(gen, "unknown");
96
+ break;
97
+ default:
98
+ json_gen_format(gen, "%d", i);
99
+ }
100
+ json_gen_integer(gen, responses[i]);
101
+ }
102
+ }
103
+ json_gen_map_close(gen);
104
+ }
105
+
106
+ static void
107
+ memcache_trace_dump(json_gen gen) {
108
+ if (stats.get_calls > 0) {
109
+ json_gen_cstr(gen, "get");
110
+ json_gen_map_open(gen);
111
+ json_gen_cstr(gen, "calls");
112
+ json_gen_integer(gen, stats.get_calls);
113
+ memcache_trace_dump_results(gen, stats.get_responses);
114
+ json_gen_map_close(gen);
115
+ }
116
+
117
+ if (stats.set_calls > 0) {
118
+ json_gen_cstr(gen, "set");
119
+ json_gen_map_open(gen);
120
+ json_gen_cstr(gen, "calls");
121
+ json_gen_integer(gen, stats.set_calls);
122
+ memcache_trace_dump_results(gen, stats.set_responses);
123
+ json_gen_map_close(gen);
124
+ }
125
+ }
126
+
127
+ void install_memcache_tracer()
128
+ {
129
+ tracer.start = memcache_trace_start;
130
+ tracer.stop = memcache_trace_stop;
131
+ tracer.reset = memcache_trace_reset;
132
+ tracer.dump = memcache_trace_dump;
133
+ tracer.id = "memcache";
134
+
135
+ trace_insert(&tracer);
136
+ }