Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: tools/android/heap_profiler/heap_dump.c

Issue 391643002: Add some convenient metadata in Android's heap profiler dump. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // The client dump tool for libheap_profiler. It attaches to a process (given 5 // The client dump tool for libheap_profiler. It attaches to a process (given
6 // its pid) and dumps all the libheap_profiler tracking information in JSON. 6 // its pid) and dumps all the libheap_profiler tracking information in JSON.
7 // The target process is frozen (SIGSTOP) while dumping, unless the -n opt. 7 // The target process is frozen (SIGSTOP) while dumping, unless the -n opt.
8 // is passed (in which case the caller is responsible for un/freezing). 8 // is passed (in which case the caller is responsible for un/freezing).
9 // The JSON output looks like this: 9 // The JSON output looks like this:
10 // { 10 // {
(...skipping 20 matching lines...) Expand all
31 // +---------------------> Index of the entry (as for "allocs" xref). 31 // +---------------------> Index of the entry (as for "allocs" xref).
32 // Indexes are hex and might not be monotonic. 32 // Indexes are hex and might not be monotonic.
33 33
34 #include <fcntl.h> 34 #include <fcntl.h>
35 #include <inttypes.h> 35 #include <inttypes.h>
36 #include <signal.h> 36 #include <signal.h>
37 #include <stdbool.h> 37 #include <stdbool.h>
38 #include <stdio.h> 38 #include <stdio.h>
39 #include <stdlib.h> 39 #include <stdlib.h>
40 #include <string.h> 40 #include <string.h>
41 #include <time.h>
41 #include <unistd.h> 42 #include <unistd.h>
42 #include <sys/stat.h> 43 #include <sys/stat.h>
43 44
44 #include "tools/android/heap_profiler/heap_profiler.h" 45 #include "tools/android/heap_profiler/heap_profiler.h"
45 46
46 47
47 static void lseek_abs(int fd, size_t off); 48 static void lseek_abs(int fd, size_t off);
49 static int read_proc_cmdline(char* cmdline, int size);
48 50
49 static int pid; 51 static int pid;
50 52
51 53
52 static int dump_process_heap(int mem_fd, FILE* fmaps, bool dump_also_allocs) { 54 static int dump_process_heap(
55 int mem_fd,
56 FILE* fmaps,
57 bool dump_also_allocs,
58 char* comment) {
53 HeapStats stats; 59 HeapStats stats;
60 time_t tm;
61 struct tm local_tm;
62 char asc_tm[64];
63 char cmdline[512];
64
65 tm = time(NULL);
66 localtime_r(&tm, &local_tm);
67 strftime(asc_tm, 64, "%Y-%m-%d %H:%M:%S%z", &local_tm);
Primiano Tucci (use gerrit) 2014/07/15 23:42:34 Can we avoid extracting the time on the device and
Dai Mikurube (NOT FULLTIME) 2014/07/16 06:24:57 Makes sense especially for the latter. Changed it
68
69 read_proc_cmdline(cmdline, 512);
54 70
55 // Look for the mmap which contains the HeapStats in the target process vmem. 71 // Look for the mmap which contains the HeapStats in the target process vmem.
56 // On Linux/Android, the libheap_profiler mmaps explicitly /dev/zero. The 72 // On Linux/Android, the libheap_profiler mmaps explicitly /dev/zero. The
57 // region furthermore starts with a magic marker to disambiguate. 73 // region furthermore starts with a magic marker to disambiguate.
58 bool stats_mmap_found = false; 74 bool stats_mmap_found = false;
59 for (;;) { 75 for (;;) {
60 char line[1024]; 76 char line[1024];
61 if (fgets(line, sizeof(line), fmaps) == NULL) 77 if (fgets(line, sizeof(line), fmaps) == NULL)
62 break; 78 break;
63 79
(...skipping 18 matching lines...) Expand all
82 } 98 }
83 99
84 if (!stats_mmap_found) { 100 if (!stats_mmap_found) {
85 fprintf(stderr, "Could not find the HeapStats area. " 101 fprintf(stderr, "Could not find the HeapStats area. "
86 "It looks like libheap_profiler is not loaded.\n"); 102 "It looks like libheap_profiler is not loaded.\n");
87 return -1; 103 return -1;
88 } 104 }
89 105
90 // Print JSON-formatted output. 106 // Print JSON-formatted output.
91 printf("{\n"); 107 printf("{\n");
108 printf(" \"pid\": %d,\n", pid);
109 printf(" \"time\": \"%s\",\n", asc_tm);
110 printf(" \"comment\": \"%s\",\n", comment);
111 printf(" \"cmdline\": \"%s\",\n", cmdline);
112 printf(" \"pagesize\": %d,\n", getpagesize());
Primiano Tucci (use gerrit) 2014/07/15 23:42:34 I'm curious, Is there any case in which this is ex
Dai Mikurube (NOT FULLTIME) 2014/07/16 06:24:57 Ah, it may not be required here. I used it in dmpr
92 printf(" \"total_allocated\": %zu,\n", stats.total_alloc_bytes); 113 printf(" \"total_allocated\": %zu,\n", stats.total_alloc_bytes);
93 printf(" \"num_allocs\": %"PRIu32",\n", stats.num_allocs); 114 printf(" \"num_allocs\": %"PRIu32",\n", stats.num_allocs);
94 printf(" \"num_stacks\": %"PRIu32",\n", stats.num_stack_traces); 115 printf(" \"num_stacks\": %"PRIu32",\n", stats.num_stack_traces);
95 116
96 uint32_t dbg_counted_allocs = 0; 117 uint32_t dbg_counted_allocs = 0;
97 size_t dbg_counted_total_alloc_bytes = 0; 118 size_t dbg_counted_total_alloc_bytes = 0;
98 bool prepend_trailing_comma = false; // JSON syntax, I hate you. 119 bool prepend_trailing_comma = false; // JSON syntax, I hate you.
99 uint32_t i; 120 uint32_t i;
100 121
101 // Dump the optional allocation table. 122 // Dump the optional allocation table.
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 char path[64]; 262 char path[64];
242 snprintf(path, sizeof(path), "/proc/%d/maps", pid); 263 snprintf(path, sizeof(path), "/proc/%d/maps", pid);
243 FILE* fmaps = fopen(path, "r"); 264 FILE* fmaps = fopen(path, "r");
244 if (fmaps == NULL) { 265 if (fmaps == NULL) {
245 fprintf(stderr, "Could not open %s.\n", path); 266 fprintf(stderr, "Could not open %s.\n", path);
246 perror("fopen"); 267 perror("fopen");
247 } 268 }
248 return fmaps; 269 return fmaps;
249 } 270 }
250 271
272 static int read_proc_cmdline(char* cmdline, int size) {
273 char path[64];
274 snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
275 FILE* fcmdline = fopen(path, "r");
Primiano Tucci (use gerrit) 2014/07/15 23:42:34 I'd personally just use raw open and read in these
Dai Mikurube (NOT FULLTIME) 2014/07/16 06:24:57 Okay, switched to open/read.
Primiano Tucci (use gerrit) 2014/07/16 16:36:18 Thanks :)
276 if (fcmdline == NULL) {
277 fprintf(stderr, "Could not open %s.\n", path);
278 perror("fopen");
279 return -1;
280 }
281 if (NULL == fgets(cmdline, size, fcmdline)) {
282 fprintf(stderr, "Could not read %s.\n", path);
283 perror("fgets");
284 return -1;
285 }
286 fclose(fcmdline);
287 return 0;
288 }
289
251 int main(int argc, char** argv) { 290 int main(int argc, char** argv) {
252 char c; 291 char c;
253 int ret = 0; 292 int ret = 0;
254 bool should_freeze_process = true; 293 bool should_freeze_process = true;
255 bool dump_also_allocs = false; 294 bool dump_also_allocs = false;
295 char comment[1024];
Primiano Tucci (use gerrit) 2014/07/15 23:42:33 What about just: char comment[1024] = { '\0' }; a
Dai Mikurube (NOT FULLTIME) 2014/07/16 06:24:57 Done.
256 296
257 297 comment[0] = '\0';
258 while (((c = getopt(argc, argv, "nx")) & 0x80) == 0) { 298 while (((c = getopt(argc, argv, "nxc:")) & 0x80) == 0) {
259 switch (c) { 299 switch (c) {
260 case 'n': 300 case 'n':
261 should_freeze_process = false; 301 should_freeze_process = false;
262 break; 302 break;
263 case 'x': 303 case 'x':
264 dump_also_allocs = true; 304 dump_also_allocs = true;
265 break; 305 break;
306 case 'c':
307 strncpy(comment, optarg, 1024);
Primiano Tucci (use gerrit) 2014/07/15 23:42:34 s/strncpy/strlcpy/. strlcpy is safer and nowadays
Dai Mikurube (NOT FULLTIME) 2014/07/16 06:24:57 Done.
308 comment[1023] = '\0';
Primiano Tucci (use gerrit) 2014/07/15 23:42:34 Precisely. By using strlcpy you don't need this an
Dai Mikurube (NOT FULLTIME) 2014/07/16 06:24:57 Acknowledged.
309 break;
266 } 310 }
267 } 311 }
268 312
269 if (optind >= argc) { 313 if (optind >= argc) {
270 printf("Usage: %s [-n] [-x] pid\n", argv[0]); 314 printf("Usage: %s [-n] [-x] [-c comment] pid\n", argv[0]);
271 return -1; 315 return -1;
272 } 316 }
273 317
274 pid = atoi(argv[optind]); 318 pid = atoi(argv[optind]);
275 319
276 if (should_freeze_process && !freeze_process()) 320 if (should_freeze_process && !freeze_process())
277 return -1; 321 return -1;
278 322
279 // Wait for the process to actually freeze. 323 // Wait for the process to actually freeze.
280 waitpid(pid, NULL, 0); 324 waitpid(pid, NULL, 0);
281 325
282 int mem_fd = open_proc_mem_fd(); 326 int mem_fd = open_proc_mem_fd();
283 if (mem_fd < 0) 327 if (mem_fd < 0)
284 ret = -1; 328 ret = -1;
285 329
286 FILE* fmaps = open_proc_maps(); 330 FILE* fmaps = open_proc_maps();
287 if (fmaps == NULL) 331 if (fmaps == NULL)
288 ret = -1; 332 ret = -1;
289 333
290 if (ret == 0) 334 if (ret == 0)
291 ret = dump_process_heap(mem_fd, fmaps, dump_also_allocs); 335 ret = dump_process_heap(mem_fd, fmaps, dump_also_allocs, comment);
292 336
293 if (should_freeze_process) 337 if (should_freeze_process)
294 kill(pid, SIGCONT); 338 kill(pid, SIGCONT);
295 339
296 // Cleanup. 340 // Cleanup.
297 fflush(stdout); 341 fflush(stdout);
298 close(mem_fd); 342 close(mem_fd);
299 fclose(fmaps); 343 fclose(fmaps);
300 return ret; 344 return ret;
301 } 345 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698