| 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 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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); |
| 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 char* filename_buffer, | |
| 270 size_t filename_buffer_length) { | |
| 271 RAW_DCHECK(heap_lock.IsHeld(), ""); | 269 RAW_DCHECK(heap_lock.IsHeld(), ""); |
| 272 RAW_DCHECK(is_on, ""); | 270 RAW_DCHECK(is_on, ""); |
| 273 RAW_DCHECK(!dumping, ""); | 271 RAW_DCHECK(!dumping, ""); |
| 274 | 272 |
| 275 if (filename_prefix == NULL) return; // we do not yet need dumping | 273 if (filename_prefix == NULL) return; // we do not yet need dumping |
| 276 | 274 |
| 277 dumping = true; | 275 dumping = true; |
| 278 | 276 |
| 279 // Make file name | 277 // Make file name |
| 278 char file_name[1000]; |
| 280 dump_count++; | 279 dump_count++; |
| 281 snprintf(filename_buffer, filename_buffer_length, "%s.%05d.%04d%s", | 280 snprintf(file_name, sizeof(file_name), "%s.%05d.%04d%s", |
| 282 filename_prefix, getpid(), dump_count, HeapProfileTable::kFileExt); | 281 filename_prefix, getpid(), dump_count, HeapProfileTable::kFileExt); |
| 283 | 282 |
| 284 // Dump the profile | 283 // Dump the profile |
| 285 RAW_VLOG(0, "Dumping heap profile to %s (%s)", filename_buffer, reason); | 284 RAW_VLOG(0, "Dumping heap profile to %s (%s)", file_name, reason); |
| 286 // We must use file routines that don't access memory, since we hold | 285 // We must use file routines that don't access memory, since we hold |
| 287 // a memory lock now. | 286 // a memory lock now. |
| 288 RawFD fd = RawOpenForWriting(filename_buffer); | 287 RawFD fd = RawOpenForWriting(file_name); |
| 289 if (fd == kIllegalRawFD) { | 288 if (fd == kIllegalRawFD) { |
| 290 RAW_LOG(ERROR, "Failed dumping heap profile to %s", filename_buffer); | 289 RAW_LOG(ERROR, "Failed dumping heap profile to %s", file_name); |
| 291 dumping = false; | 290 dumping = false; |
| 292 return; | 291 return; |
| 293 } | 292 } |
| 294 | 293 |
| 295 // 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. |
| 296 // 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. |
| 297 if (global_profiler_buffer == NULL) { | 296 if (global_profiler_buffer == NULL) { |
| 298 global_profiler_buffer = | 297 global_profiler_buffer = |
| 299 reinterpret_cast<char*>(ProfilerMalloc(kProfileBufferSize)); | 298 reinterpret_cast<char*>(ProfilerMalloc(kProfileBufferSize)); |
| 300 } | 299 } |
| 301 | 300 |
| 302 char* profile = DoGetHeapProfileLocked(global_profiler_buffer, | 301 char* profile = DoGetHeapProfileLocked(global_profiler_buffer, |
| 303 kProfileBufferSize); | 302 kProfileBufferSize); |
| 304 RawWrite(fd, profile, strlen(profile)); | 303 RawWrite(fd, profile, strlen(profile)); |
| 305 RawClose(fd); | 304 RawClose(fd); |
| 306 | 305 |
| 307 #if defined(TYPE_PROFILING) | 306 #if defined(TYPE_PROFILING) |
| 308 if (FLAGS_heap_profile_type_statistics) { | 307 if (FLAGS_heap_profile_type_statistics) { |
| 309 snprintf(filename_buffer, filename_buffer_length, "%s.%05d.%04d.type", | 308 snprintf(file_name, sizeof(file_name), "%s.%05d.%04d.type", |
| 310 filename_prefix, getpid(), dump_count); | 309 filename_prefix, getpid(), dump_count); |
| 311 RAW_VLOG(0, "Dumping type statistics to %s", filename_buffer); | 310 RAW_VLOG(0, "Dumping type statistics to %s", file_name); |
| 312 heap_profile->DumpTypeStatistics(filename_buffer); | 311 heap_profile->DumpTypeStatistics(file_name); |
| 313 } | 312 } |
| 314 #endif // defined(TYPE_PROFILING) | 313 #endif // defined(TYPE_PROFILING) |
| 315 | 314 |
| 316 dumping = false; | 315 dumping = false; |
| 317 } | 316 } |
| 318 | 317 |
| 319 //---------------------------------------------------------------------- | 318 //---------------------------------------------------------------------- |
| 320 // Profile collection | 319 // Profile collection |
| 321 //---------------------------------------------------------------------- | 320 //---------------------------------------------------------------------- |
| 322 | 321 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 351 need_to_dump = true; | 350 need_to_dump = true; |
| 352 } else if (FLAGS_heap_profile_time_interval > 0 && | 351 } else if (FLAGS_heap_profile_time_interval > 0 && |
| 353 current_time - last_dump_time >= | 352 current_time - last_dump_time >= |
| 354 FLAGS_heap_profile_time_interval) { | 353 FLAGS_heap_profile_time_interval) { |
| 355 snprintf(buf, sizeof(buf), "%d sec since the last dump", | 354 snprintf(buf, sizeof(buf), "%d sec since the last dump", |
| 356 current_time - last_dump_time); | 355 current_time - last_dump_time); |
| 357 need_to_dump = true; | 356 need_to_dump = true; |
| 358 last_dump_time = current_time; | 357 last_dump_time = current_time; |
| 359 } | 358 } |
| 360 if (need_to_dump) { | 359 if (need_to_dump) { |
| 361 char filename_buffer[1000]; | 360 DumpProfileLocked(buf); |
| 362 DumpProfileLocked(buf, filename_buffer, sizeof(filename_buffer)); | |
| 363 | 361 |
| 364 last_dump_alloc = total.alloc_size; | 362 last_dump_alloc = total.alloc_size; |
| 365 last_dump_free = total.free_size; | 363 last_dump_free = total.free_size; |
| 366 if (inuse_bytes > high_water_mark) | 364 if (inuse_bytes > high_water_mark) |
| 367 high_water_mark = inuse_bytes; | 365 high_water_mark = inuse_bytes; |
| 368 } | 366 } |
| 369 } | 367 } |
| 370 } | 368 } |
| 371 | 369 |
| 372 // Record an allocation in the profile. | 370 // Record an allocation in the profile. |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 if (FLAGS_mmap_profile) { | 603 if (FLAGS_mmap_profile) { |
| 606 MemoryRegionMap::Shutdown(); | 604 MemoryRegionMap::Shutdown(); |
| 607 } | 605 } |
| 608 | 606 |
| 609 is_on = false; | 607 is_on = false; |
| 610 } | 608 } |
| 611 | 609 |
| 612 extern "C" void HeapProfilerDump(const char* reason) { | 610 extern "C" void HeapProfilerDump(const char* reason) { |
| 613 SpinLockHolder l(&heap_lock); | 611 SpinLockHolder l(&heap_lock); |
| 614 if (is_on && !dumping) { | 612 if (is_on && !dumping) { |
| 615 char filename_buffer[1000]; | 613 DumpProfileLocked(reason); |
| 616 DumpProfileLocked(reason, filename_buffer, sizeof(filename_buffer)); | |
| 617 } | |
| 618 } | |
| 619 | |
| 620 extern "C" void HeapProfilerDumpWithFileName(const char* reason, | |
| 621 char* dumped_filename_buffer, | |
| 622 int filename_buffer_length) { | |
| 623 SpinLockHolder l(&heap_lock); | |
| 624 if (is_on && !dumping) { | |
| 625 DumpProfileLocked(reason, dumped_filename_buffer, filename_buffer_length); | |
| 626 } | 614 } |
| 627 } | 615 } |
| 628 | 616 |
| 629 extern "C" void HeapProfilerMarkBaseline() { | 617 extern "C" void HeapProfilerMarkBaseline() { |
| 630 SpinLockHolder l(&heap_lock); | 618 SpinLockHolder l(&heap_lock); |
| 631 | 619 |
| 632 if (!is_on) return; | 620 if (!is_on) return; |
| 633 | 621 |
| 634 heap_profile->MarkCurrentAllocations(HeapProfileTable::MARK_ONE); | 622 heap_profile->MarkCurrentAllocations(HeapProfileTable::MARK_ONE); |
| 635 } | 623 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 677 | 665 |
| 678 // class used for finalization -- dumps the heap-profile at program exit | 666 // class used for finalization -- dumps the heap-profile at program exit |
| 679 struct HeapProfileEndWriter { | 667 struct HeapProfileEndWriter { |
| 680 ~HeapProfileEndWriter() { HeapProfilerDump("Exiting"); } | 668 ~HeapProfileEndWriter() { HeapProfilerDump("Exiting"); } |
| 681 }; | 669 }; |
| 682 | 670 |
| 683 // 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 |
| 684 static const TCMallocGuard tcmalloc_initializer; | 672 static const TCMallocGuard tcmalloc_initializer; |
| 685 REGISTER_MODULE_INITIALIZER(heapprofiler, HeapProfilerInit()); | 673 REGISTER_MODULE_INITIALIZER(heapprofiler, HeapProfilerInit()); |
| 686 static HeapProfileEndWriter heap_profile_end_writer; | 674 static HeapProfileEndWriter heap_profile_end_writer; |
| OLD | NEW |