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 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
218 static int64 last_dump_time = 0; // The time of the last dump | 218 static int64 last_dump_time = 0; // The time of the last dump |
219 | 219 |
220 static HeapProfileTable* heap_profile = NULL; // the heap profile table | 220 static HeapProfileTable* heap_profile = NULL; // the heap profile table |
221 static DeepHeapProfile* deep_profile = NULL; // deep memory profiler | 221 static DeepHeapProfile* deep_profile = NULL; // deep memory profiler |
222 | 222 |
223 //---------------------------------------------------------------------- | 223 //---------------------------------------------------------------------- |
224 // Profile generation | 224 // Profile generation |
225 //---------------------------------------------------------------------- | 225 //---------------------------------------------------------------------- |
226 | 226 |
227 // Input must be a buffer of size at least 1MB. | 227 // Input must be a buffer of size at least 1MB. |
228 static char* DoGetHeapProfileLocked(char* buf, int buflen) { | 228 static char* DoGetHeapProfileLocked(char* buf, int buflen, const char* reason) { |
Alexander Potapenko
2013/05/27 08:54:44
It's probably better to put |reason| first. I don'
Dai Mikurube (NOT FULLTIME)
2013/05/27 10:08:24
Reasonable, too. Done.
| |
229 // We used to be smarter about estimating the required memory and | 229 // We used to be smarter about estimating the required memory and |
230 // then capping it to 1MB and generating the profile into that. | 230 // then capping it to 1MB and generating the profile into that. |
231 if (buf == NULL || buflen < 1) | 231 if (buf == NULL || buflen < 1) |
232 return NULL; | 232 return NULL; |
233 | 233 |
234 RAW_DCHECK(heap_lock.IsHeld(), ""); | 234 RAW_DCHECK(heap_lock.IsHeld(), ""); |
235 int bytes_written = 0; | 235 int bytes_written = 0; |
236 if (is_on) { | 236 if (is_on) { |
237 HeapProfileTable::Stats const stats = heap_profile->total(); | 237 HeapProfileTable::Stats const stats = heap_profile->total(); |
238 (void)stats; // avoid an unused-variable warning in non-debug mode. | 238 (void)stats; // avoid an unused-variable warning in non-debug mode. |
239 if (deep_profile) { | 239 if (deep_profile) { |
240 bytes_written = deep_profile->FillOrderedProfile(buf, buflen - 1); | 240 bytes_written = deep_profile->FillOrderedProfile(buf, buflen - 1, reason); |
241 } else { | 241 } else { |
242 bytes_written = heap_profile->FillOrderedProfile(buf, buflen - 1); | 242 bytes_written = heap_profile->FillOrderedProfile(buf, buflen - 1); |
243 } | 243 } |
244 // FillOrderedProfile should not reduce the set of active mmap-ed regions, | 244 // FillOrderedProfile should not reduce the set of active mmap-ed regions, |
245 // hence MemoryRegionMap will let us remove everything we've added above: | 245 // hence MemoryRegionMap will let us remove everything we've added above: |
246 RAW_DCHECK(stats.Equivalent(heap_profile->total()), ""); | 246 RAW_DCHECK(stats.Equivalent(heap_profile->total()), ""); |
247 // if this fails, we somehow removed by FillOrderedProfile | 247 // if this fails, we somehow removed by FillOrderedProfile |
248 // more than we have added. | 248 // more than we have added. |
249 } | 249 } |
250 buf[bytes_written] = '\0'; | 250 buf[bytes_written] = '\0'; |
251 RAW_DCHECK(bytes_written == strlen(buf), ""); | 251 RAW_DCHECK(bytes_written == strlen(buf), ""); |
252 | 252 |
253 return buf; | 253 return buf; |
254 } | 254 } |
255 | 255 |
256 extern "C" char* GetHeapProfile() { | 256 extern "C" char* GetHeapProfile() { |
257 // Use normal malloc: we return the profile to the user to free it: | 257 // Use normal malloc: we return the profile to the user to free it: |
258 char* buffer = reinterpret_cast<char*>(malloc(kProfileBufferSize)); | 258 char* buffer = reinterpret_cast<char*>(malloc(kProfileBufferSize)); |
259 SpinLockHolder l(&heap_lock); | 259 SpinLockHolder l(&heap_lock); |
260 return DoGetHeapProfileLocked(buffer, kProfileBufferSize); | 260 return DoGetHeapProfileLocked(buffer, kProfileBufferSize, NULL); |
Alexander Potapenko
2013/05/27 08:54:44
/*reason*/NULL
Dai Mikurube (NOT FULLTIME)
2013/05/27 10:08:24
Done.
| |
261 } | 261 } |
262 | 262 |
263 // defined below | 263 // defined below |
264 static void NewHook(const void* ptr, size_t size); | 264 static void NewHook(const void* ptr, size_t size); |
265 static void DeleteHook(const void* ptr); | 265 static void DeleteHook(const void* ptr); |
266 | 266 |
267 // Helper for HeapProfilerDump. | 267 // Helper for HeapProfilerDump. |
268 static void DumpProfileLocked(const char* reason) { | 268 static void DumpProfileLocked(const char* reason) { |
269 RAW_DCHECK(heap_lock.IsHeld(), ""); | 269 RAW_DCHECK(heap_lock.IsHeld(), ""); |
270 RAW_DCHECK(is_on, ""); | 270 RAW_DCHECK(is_on, ""); |
(...skipping 21 matching lines...) Expand all Loading... | |
292 } | 292 } |
293 | 293 |
294 // This case may be impossible, but it's best to be safe. | 294 // This case may be impossible, but it's best to be safe. |
295 // It's safe to use the global buffer: we're protected by heap_lock. | 295 // It's safe to use the global buffer: we're protected by heap_lock. |
296 if (global_profiler_buffer == NULL) { | 296 if (global_profiler_buffer == NULL) { |
297 global_profiler_buffer = | 297 global_profiler_buffer = |
298 reinterpret_cast<char*>(ProfilerMalloc(kProfileBufferSize)); | 298 reinterpret_cast<char*>(ProfilerMalloc(kProfileBufferSize)); |
299 } | 299 } |
300 | 300 |
301 char* profile = DoGetHeapProfileLocked(global_profiler_buffer, | 301 char* profile = DoGetHeapProfileLocked(global_profiler_buffer, |
302 kProfileBufferSize); | 302 kProfileBufferSize, reason); |
303 RawWrite(fd, profile, strlen(profile)); | 303 RawWrite(fd, profile, strlen(profile)); |
304 RawClose(fd); | 304 RawClose(fd); |
305 | 305 |
306 #if defined(TYPE_PROFILING) | 306 #if defined(TYPE_PROFILING) |
307 if (FLAGS_heap_profile_type_statistics) { | 307 if (FLAGS_heap_profile_type_statistics) { |
308 snprintf(file_name, sizeof(file_name), "%s.%05d.%04d.type", | 308 snprintf(file_name, sizeof(file_name), "%s.%05d.%04d.type", |
309 filename_prefix, getpid(), dump_count); | 309 filename_prefix, getpid(), dump_count); |
310 RAW_VLOG(0, "Dumping type statistics to %s", file_name); | 310 RAW_VLOG(0, "Dumping type statistics to %s", file_name); |
311 heap_profile->DumpTypeStatistics(file_name); | 311 heap_profile->DumpTypeStatistics(file_name); |
312 } | 312 } |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
665 | 665 |
666 // class used for finalization -- dumps the heap-profile at program exit | 666 // class used for finalization -- dumps the heap-profile at program exit |
667 struct HeapProfileEndWriter { | 667 struct HeapProfileEndWriter { |
668 ~HeapProfileEndWriter() { HeapProfilerDump("Exiting"); } | 668 ~HeapProfileEndWriter() { HeapProfilerDump("Exiting"); } |
669 }; | 669 }; |
670 | 670 |
671 // We want to make sure tcmalloc is up and running before starting the profiler | 671 // We want to make sure tcmalloc is up and running before starting the profiler |
672 static const TCMallocGuard tcmalloc_initializer; | 672 static const TCMallocGuard tcmalloc_initializer; |
673 REGISTER_MODULE_INITIALIZER(heapprofiler, HeapProfilerInit()); | 673 REGISTER_MODULE_INITIALIZER(heapprofiler, HeapProfilerInit()); |
674 static HeapProfileEndWriter heap_profile_end_writer; | 674 static HeapProfileEndWriter heap_profile_end_writer; |
OLD | NEW |