Chromium Code Reviews| 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 |