OLD | NEW |
1 // Copyright (c) 2005, Google Inc. | 1 // Copyright (c) 2005, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 #include "base/basictypes.h" // for PRId64, among other things | 61 #include "base/basictypes.h" // for PRId64, among other things |
62 #include "base/googleinit.h" | 62 #include "base/googleinit.h" |
63 #include "base/commandlineflags.h" | 63 #include "base/commandlineflags.h" |
64 #include "malloc_hook-inl.h" | 64 #include "malloc_hook-inl.h" |
65 #include "tcmalloc_guard.h" | 65 #include "tcmalloc_guard.h" |
66 #include <google/malloc_hook.h> | 66 #include <google/malloc_hook.h> |
67 #include <google/malloc_extension.h> | 67 #include <google/malloc_extension.h> |
68 #include "base/spinlock.h" | 68 #include "base/spinlock.h" |
69 #include "base/low_level_alloc.h" | 69 #include "base/low_level_alloc.h" |
70 #include "base/sysinfo.h" // for GetUniquePathFromEnv() | 70 #include "base/sysinfo.h" // for GetUniquePathFromEnv() |
| 71 #include "deep-heap-profile.h" |
71 #include "heap-profile-table.h" | 72 #include "heap-profile-table.h" |
72 #include "memory_region_map.h" | 73 #include "memory_region_map.h" |
73 | 74 |
74 | 75 |
75 #ifndef PATH_MAX | 76 #ifndef PATH_MAX |
76 #ifdef MAXPATHLEN | 77 #ifdef MAXPATHLEN |
77 #define PATH_MAX MAXPATHLEN | 78 #define PATH_MAX MAXPATHLEN |
78 #else | 79 #else |
79 #define PATH_MAX 4096 // seems conservative for max filename len! | 80 #define PATH_MAX 4096 // seems conservative for max filename len! |
80 #endif | 81 #endif |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 DEFINE_bool(mmap_log, | 115 DEFINE_bool(mmap_log, |
115 EnvToBool("HEAP_PROFILE_MMAP_LOG", false), | 116 EnvToBool("HEAP_PROFILE_MMAP_LOG", false), |
116 "Should mmap/munmap calls be logged?"); | 117 "Should mmap/munmap calls be logged?"); |
117 DEFINE_bool(mmap_profile, | 118 DEFINE_bool(mmap_profile, |
118 EnvToBool("HEAP_PROFILE_MMAP", false), | 119 EnvToBool("HEAP_PROFILE_MMAP", false), |
119 "If heap-profiling is on, also profile mmap, mremap, and sbrk)"); | 120 "If heap-profiling is on, also profile mmap, mremap, and sbrk)"); |
120 DEFINE_bool(only_mmap_profile, | 121 DEFINE_bool(only_mmap_profile, |
121 EnvToBool("HEAP_PROFILE_ONLY_MMAP", false), | 122 EnvToBool("HEAP_PROFILE_ONLY_MMAP", false), |
122 "If heap-profiling is on, only profile mmap, mremap, and sbrk; " | 123 "If heap-profiling is on, only profile mmap, mremap, and sbrk; " |
123 "do not profile malloc/new/etc"); | 124 "do not profile malloc/new/etc"); |
| 125 DEFINE_bool(deep_heap_profile, |
| 126 EnvToBool("DEEP_HEAP_PROFILE", false), |
| 127 "If heap-profiling is on, profile deeper (only on Linux)"); |
124 | 128 |
125 | 129 |
126 //---------------------------------------------------------------------- | 130 //---------------------------------------------------------------------- |
127 // Locking | 131 // Locking |
128 //---------------------------------------------------------------------- | 132 //---------------------------------------------------------------------- |
129 | 133 |
130 // A pthread_mutex has way too much lock contention to be used here. | 134 // A pthread_mutex has way too much lock contention to be used here. |
131 // | 135 // |
132 // I would like to use Mutex, but it can call malloc(), | 136 // I would like to use Mutex, but it can call malloc(), |
133 // which can cause us to fall into an infinite recursion. | 137 // which can cause us to fall into an infinite recursion. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 static bool dumping = false; // Dumping status to prevent recursion | 174 static bool dumping = false; // Dumping status to prevent recursion |
171 static char* filename_prefix = NULL; // Prefix used for profile file names | 175 static char* filename_prefix = NULL; // Prefix used for profile file names |
172 // (NULL if no need for dumping yet) | 176 // (NULL if no need for dumping yet) |
173 static int dump_count = 0; // How many dumps so far | 177 static int dump_count = 0; // How many dumps so far |
174 static int64 last_dump_alloc = 0; // alloc_size when did we last dump | 178 static int64 last_dump_alloc = 0; // alloc_size when did we last dump |
175 static int64 last_dump_free = 0; // free_size when did we last dump | 179 static int64 last_dump_free = 0; // free_size when did we last dump |
176 static int64 high_water_mark = 0; // In-use-bytes at last high-water dump | 180 static int64 high_water_mark = 0; // In-use-bytes at last high-water dump |
177 static int64 last_dump_time = 0; // The time of the last dump | 181 static int64 last_dump_time = 0; // The time of the last dump |
178 | 182 |
179 static HeapProfileTable* heap_profile = NULL; // the heap profile table | 183 static HeapProfileTable* heap_profile = NULL; // the heap profile table |
| 184 static DeepHeapProfile* deep_profile = NULL; // deep memory profiler |
180 | 185 |
181 //---------------------------------------------------------------------- | 186 //---------------------------------------------------------------------- |
182 // Profile generation | 187 // Profile generation |
183 //---------------------------------------------------------------------- | 188 //---------------------------------------------------------------------- |
184 | 189 |
185 // Input must be a buffer of size at least 1MB. | 190 // Input must be a buffer of size at least 1MB. |
186 static char* DoGetHeapProfileLocked(char* buf, int buflen) { | 191 static char* DoGetHeapProfileLocked(char* buf, int buflen) { |
187 // We used to be smarter about estimating the required memory and | 192 // We used to be smarter about estimating the required memory and |
188 // then capping it to 1MB and generating the profile into that. | 193 // then capping it to 1MB and generating the profile into that. |
189 if (buf == NULL || buflen < 1) | 194 if (buf == NULL || buflen < 1) |
190 return NULL; | 195 return NULL; |
191 | 196 |
192 RAW_DCHECK(heap_lock.IsHeld(), ""); | 197 RAW_DCHECK(heap_lock.IsHeld(), ""); |
193 int bytes_written = 0; | 198 int bytes_written = 0; |
194 if (is_on) { | 199 if (is_on) { |
195 if (FLAGS_mmap_profile) { | 200 if (FLAGS_mmap_profile) { |
196 heap_profile->RefreshMMapData(); | 201 heap_profile->RefreshMMapData(); |
197 } | 202 } |
198 bytes_written = heap_profile->FillOrderedProfile(buf, buflen - 1); | 203 if (FLAGS_deep_heap_profile) { |
| 204 bytes_written = deep_profile->FillOrderedProfile(buf, buflen - 1); |
| 205 } else { |
| 206 bytes_written = heap_profile->FillOrderedProfile(buf, buflen - 1); |
| 207 } |
199 if (FLAGS_mmap_profile) { | 208 if (FLAGS_mmap_profile) { |
200 heap_profile->ClearMMapData(); | 209 heap_profile->ClearMMapData(); |
201 } | 210 } |
202 } | 211 } |
203 buf[bytes_written] = '\0'; | 212 buf[bytes_written] = '\0'; |
204 RAW_DCHECK(bytes_written == strlen(buf), ""); | 213 RAW_DCHECK(bytes_written == strlen(buf), ""); |
205 | 214 |
206 return buf; | 215 return buf; |
207 } | 216 } |
208 | 217 |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 reinterpret_cast<char*>(ProfilerMalloc(kProfileBufferSize)); | 463 reinterpret_cast<char*>(ProfilerMalloc(kProfileBufferSize)); |
455 | 464 |
456 heap_profile = new(ProfilerMalloc(sizeof(HeapProfileTable))) | 465 heap_profile = new(ProfilerMalloc(sizeof(HeapProfileTable))) |
457 HeapProfileTable(ProfilerMalloc, ProfilerFree); | 466 HeapProfileTable(ProfilerMalloc, ProfilerFree); |
458 | 467 |
459 last_dump_alloc = 0; | 468 last_dump_alloc = 0; |
460 last_dump_free = 0; | 469 last_dump_free = 0; |
461 high_water_mark = 0; | 470 high_water_mark = 0; |
462 last_dump_time = 0; | 471 last_dump_time = 0; |
463 | 472 |
| 473 if (FLAGS_deep_heap_profile) { |
| 474 // Initialize deep memory profiler |
| 475 RAW_VLOG(0, "[%d] Starting a deep memory profiler", getpid()); |
| 476 deep_profile = new(ProfilerMalloc(sizeof(DeepHeapProfile))) |
| 477 DeepHeapProfile(heap_profile, prefix); |
| 478 } |
| 479 |
464 // We do not reset dump_count so if the user does a sequence of | 480 // We do not reset dump_count so if the user does a sequence of |
465 // HeapProfilerStart/HeapProfileStop, we will get a continuous | 481 // HeapProfilerStart/HeapProfileStop, we will get a continuous |
466 // sequence of profiles. | 482 // sequence of profiles. |
467 | 483 |
468 if (FLAGS_only_mmap_profile == false) { | 484 if (FLAGS_only_mmap_profile == false) { |
469 // Now set the hooks that capture new/delete and malloc/free. | 485 // Now set the hooks that capture new/delete and malloc/free. |
470 RAW_CHECK(MallocHook::AddNewHook(&NewHook), ""); | 486 RAW_CHECK(MallocHook::AddNewHook(&NewHook), ""); |
471 RAW_CHECK(MallocHook::AddDeleteHook(&DeleteHook), ""); | 487 RAW_CHECK(MallocHook::AddDeleteHook(&DeleteHook), ""); |
472 } | 488 } |
473 | 489 |
(...skipping 21 matching lines...) Expand all Loading... |
495 RAW_CHECK(MallocHook::RemoveDeleteHook(&DeleteHook), ""); | 511 RAW_CHECK(MallocHook::RemoveDeleteHook(&DeleteHook), ""); |
496 } | 512 } |
497 if (FLAGS_mmap_log) { | 513 if (FLAGS_mmap_log) { |
498 // Restore mmap/sbrk hooks, checking that our hooks were set: | 514 // Restore mmap/sbrk hooks, checking that our hooks were set: |
499 RAW_CHECK(MallocHook::RemoveMmapHook(&MmapHook), ""); | 515 RAW_CHECK(MallocHook::RemoveMmapHook(&MmapHook), ""); |
500 RAW_CHECK(MallocHook::RemoveMremapHook(&MremapHook), ""); | 516 RAW_CHECK(MallocHook::RemoveMremapHook(&MremapHook), ""); |
501 RAW_CHECK(MallocHook::RemoveSbrkHook(&SbrkHook), ""); | 517 RAW_CHECK(MallocHook::RemoveSbrkHook(&SbrkHook), ""); |
502 RAW_CHECK(MallocHook::RemoveMunmapHook(&MunmapHook), ""); | 518 RAW_CHECK(MallocHook::RemoveMunmapHook(&MunmapHook), ""); |
503 } | 519 } |
504 | 520 |
| 521 if (FLAGS_deep_heap_profile) { |
| 522 // free deep memory profiler |
| 523 deep_profile->~DeepHeapProfile(); |
| 524 ProfilerFree(deep_profile); |
| 525 deep_profile = NULL; |
| 526 } |
| 527 |
505 // free profile | 528 // free profile |
506 heap_profile->~HeapProfileTable(); | 529 heap_profile->~HeapProfileTable(); |
507 ProfilerFree(heap_profile); | 530 ProfilerFree(heap_profile); |
508 heap_profile = NULL; | 531 heap_profile = NULL; |
509 | 532 |
510 // free output-buffer memory | 533 // free output-buffer memory |
511 ProfilerFree(global_profiler_buffer); | 534 ProfilerFree(global_profiler_buffer); |
512 | 535 |
513 // free prefix | 536 // free prefix |
514 ProfilerFree(filename_prefix); | 537 ProfilerFree(filename_prefix); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 | 582 |
560 // class used for finalization -- dumps the heap-profile at program exit | 583 // class used for finalization -- dumps the heap-profile at program exit |
561 struct HeapProfileEndWriter { | 584 struct HeapProfileEndWriter { |
562 ~HeapProfileEndWriter() { HeapProfilerDump("Exiting"); } | 585 ~HeapProfileEndWriter() { HeapProfilerDump("Exiting"); } |
563 }; | 586 }; |
564 | 587 |
565 // We want to make sure tcmalloc is up and running before starting the profiler | 588 // We want to make sure tcmalloc is up and running before starting the profiler |
566 static const TCMallocGuard tcmalloc_initializer; | 589 static const TCMallocGuard tcmalloc_initializer; |
567 REGISTER_MODULE_INITIALIZER(heapprofiler, HeapProfilerInit()); | 590 REGISTER_MODULE_INITIALIZER(heapprofiler, HeapProfilerInit()); |
568 static HeapProfileEndWriter heap_profile_end_writer; | 591 static HeapProfileEndWriter heap_profile_end_writer; |
OLD | NEW |