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 |