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 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
265 char* buffer = reinterpret_cast<char*>(malloc(kProfileBufferSize)); | 265 char* buffer = reinterpret_cast<char*>(malloc(kProfileBufferSize)); |
266 SpinLockHolder l(&heap_lock); | 266 SpinLockHolder l(&heap_lock); |
267 return DoGetHeapProfileLocked(buffer, kProfileBufferSize); | 267 return DoGetHeapProfileLocked(buffer, kProfileBufferSize); |
268 } | 268 } |
269 | 269 |
270 // defined below | 270 // defined below |
271 static void NewHook(const void* ptr, size_t size); | 271 static void NewHook(const void* ptr, size_t size); |
272 static void DeleteHook(const void* ptr); | 272 static void DeleteHook(const void* ptr); |
273 | 273 |
274 // Helper for HeapProfilerDump. | 274 // Helper for HeapProfilerDump. |
275 static void DumpProfileLocked(const char* reason) { | 275 static void DumpProfileLocked(const char* reason, |
276 char* filename_buffer, | |
277 int filename_buffer_length) { | |
jar (doing other things)
2013/02/14 23:30:09
nit: int-->size_t
Dai Mikurube (NOT FULLTIME)
2013/02/15 03:30:42
Done.
Hmm, int and size_t are mixed for size-like
| |
276 RAW_DCHECK(heap_lock.IsHeld(), ""); | 278 RAW_DCHECK(heap_lock.IsHeld(), ""); |
277 RAW_DCHECK(is_on, ""); | 279 RAW_DCHECK(is_on, ""); |
278 RAW_DCHECK(!dumping, ""); | 280 RAW_DCHECK(!dumping, ""); |
279 | 281 |
280 if (filename_prefix == NULL) return; // we do not yet need dumping | 282 if (filename_prefix == NULL) return; // we do not yet need dumping |
281 | 283 |
282 dumping = true; | 284 dumping = true; |
283 | 285 |
284 // Make file name | 286 // Make file name |
285 char file_name[1000]; | |
286 dump_count++; | 287 dump_count++; |
287 snprintf(file_name, sizeof(file_name), "%s.%05d.%04d%s", | 288 snprintf(filename_buffer, filename_buffer_length, "%s.%05d.%04d%s", |
288 filename_prefix, getpid(), dump_count, HeapProfileTable::kFileExt); | 289 filename_prefix, getpid(), dump_count, HeapProfileTable::kFileExt); |
289 | 290 |
290 // Dump the profile | 291 // Dump the profile |
291 RAW_VLOG(0, "Dumping heap profile to %s (%s)", file_name, reason); | 292 RAW_VLOG(0, "Dumping heap profile to %s (%s)", filename_buffer, reason); |
292 // We must use file routines that don't access memory, since we hold | 293 // We must use file routines that don't access memory, since we hold |
293 // a memory lock now. | 294 // a memory lock now. |
294 RawFD fd = RawOpenForWriting(file_name); | 295 RawFD fd = RawOpenForWriting(filename_buffer); |
295 if (fd == kIllegalRawFD) { | 296 if (fd == kIllegalRawFD) { |
296 RAW_LOG(ERROR, "Failed dumping heap profile to %s", file_name); | 297 RAW_LOG(ERROR, "Failed dumping heap profile to %s", filename_buffer); |
297 dumping = false; | 298 dumping = false; |
298 return; | 299 return; |
299 } | 300 } |
300 | 301 |
301 // This case may be impossible, but it's best to be safe. | 302 // This case may be impossible, but it's best to be safe. |
302 // It's safe to use the global buffer: we're protected by heap_lock. | 303 // It's safe to use the global buffer: we're protected by heap_lock. |
303 if (global_profiler_buffer == NULL) { | 304 if (global_profiler_buffer == NULL) { |
304 global_profiler_buffer = | 305 global_profiler_buffer = |
305 reinterpret_cast<char*>(ProfilerMalloc(kProfileBufferSize)); | 306 reinterpret_cast<char*>(ProfilerMalloc(kProfileBufferSize)); |
306 } | 307 } |
307 | 308 |
308 char* profile = DoGetHeapProfileLocked(global_profiler_buffer, | 309 char* profile = DoGetHeapProfileLocked(global_profiler_buffer, |
309 kProfileBufferSize); | 310 kProfileBufferSize); |
310 RawWrite(fd, profile, strlen(profile)); | 311 RawWrite(fd, profile, strlen(profile)); |
311 RawClose(fd); | 312 RawClose(fd); |
312 | 313 |
313 #if defined(TYPE_PROFILING) | 314 #if defined(TYPE_PROFILING) |
314 if (FLAGS_heap_profile_type_statistics) { | 315 if (FLAGS_heap_profile_type_statistics) { |
315 snprintf(file_name, sizeof(file_name), "%s.%05d.%04d.type", | 316 snprintf(filename_buffer, filename_buffer_length, "%s.%05d.%04d.type", |
316 filename_prefix, getpid(), dump_count); | 317 filename_prefix, getpid(), dump_count); |
317 RAW_VLOG(0, "Dumping type statistics to %s", file_name); | 318 RAW_VLOG(0, "Dumping type statistics to %s", filename_buffer); |
318 heap_profile->DumpTypeStatistics(file_name); | 319 heap_profile->DumpTypeStatistics(filename_buffer); |
319 } | 320 } |
320 #endif // defined(TYPE_PROFILING) | 321 #endif // defined(TYPE_PROFILING) |
321 | 322 |
322 dumping = false; | 323 dumping = false; |
323 } | 324 } |
324 | 325 |
325 //---------------------------------------------------------------------- | 326 //---------------------------------------------------------------------- |
326 // Profile collection | 327 // Profile collection |
327 //---------------------------------------------------------------------- | 328 //---------------------------------------------------------------------- |
328 | 329 |
(...skipping 28 matching lines...) Expand all Loading... | |
357 need_to_dump = true; | 358 need_to_dump = true; |
358 } else if (FLAGS_heap_profile_time_interval > 0 && | 359 } else if (FLAGS_heap_profile_time_interval > 0 && |
359 current_time - last_dump_time >= | 360 current_time - last_dump_time >= |
360 FLAGS_heap_profile_time_interval) { | 361 FLAGS_heap_profile_time_interval) { |
361 snprintf(buf, sizeof(buf), "%d sec since the last dump", | 362 snprintf(buf, sizeof(buf), "%d sec since the last dump", |
362 current_time - last_dump_time); | 363 current_time - last_dump_time); |
363 need_to_dump = true; | 364 need_to_dump = true; |
364 last_dump_time = current_time; | 365 last_dump_time = current_time; |
365 } | 366 } |
366 if (need_to_dump) { | 367 if (need_to_dump) { |
367 DumpProfileLocked(buf); | 368 char filename_buffer[1000]; |
369 DumpProfileLocked(buf, filename_buffer, sizeof(filename_buffer)); | |
368 | 370 |
369 last_dump_alloc = total.alloc_size; | 371 last_dump_alloc = total.alloc_size; |
370 last_dump_free = total.free_size; | 372 last_dump_free = total.free_size; |
371 if (inuse_bytes > high_water_mark) | 373 if (inuse_bytes > high_water_mark) |
372 high_water_mark = inuse_bytes; | 374 high_water_mark = inuse_bytes; |
373 } | 375 } |
374 } | 376 } |
375 } | 377 } |
376 | 378 |
377 // Record an allocation in the profile. | 379 // Record an allocation in the profile. |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
612 if (FLAGS_mmap_profile) { | 614 if (FLAGS_mmap_profile) { |
613 MemoryRegionMap::Shutdown(); | 615 MemoryRegionMap::Shutdown(); |
614 } | 616 } |
615 | 617 |
616 is_on = false; | 618 is_on = false; |
617 } | 619 } |
618 | 620 |
619 extern "C" void HeapProfilerDump(const char* reason) { | 621 extern "C" void HeapProfilerDump(const char* reason) { |
620 SpinLockHolder l(&heap_lock); | 622 SpinLockHolder l(&heap_lock); |
621 if (is_on && !dumping) { | 623 if (is_on && !dumping) { |
622 DumpProfileLocked(reason); | 624 char filename_buffer[1000]; |
625 DumpProfileLocked(reason, filename_buffer, sizeof(filename_buffer)); | |
623 } | 626 } |
624 } | 627 } |
625 | 628 |
629 extern "C" void HeapProfilerDumpWithFileName(const char* reason, | |
630 char* dumped_filename_buffer, | |
631 int filename_buffer_length) { | |
632 SpinLockHolder l(&heap_lock); | |
633 if (is_on && !dumping) { | |
634 DumpProfileLocked(reason, dumped_filename_buffer, filename_buffer_length); | |
635 } | |
636 } | |
637 | |
626 extern "C" void HeapProfilerMarkBaseline() { | 638 extern "C" void HeapProfilerMarkBaseline() { |
627 SpinLockHolder l(&heap_lock); | 639 SpinLockHolder l(&heap_lock); |
628 | 640 |
629 if (!is_on) return; | 641 if (!is_on) return; |
630 | 642 |
631 heap_profile->MarkCurrentAllocations(HeapProfileTable::MARK_ONE); | 643 heap_profile->MarkCurrentAllocations(HeapProfileTable::MARK_ONE); |
632 } | 644 } |
633 | 645 |
634 extern "C" void HeapProfilerMarkInteresting() { | 646 extern "C" void HeapProfilerMarkInteresting() { |
635 SpinLockHolder l(&heap_lock); | 647 SpinLockHolder l(&heap_lock); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
674 | 686 |
675 // class used for finalization -- dumps the heap-profile at program exit | 687 // class used for finalization -- dumps the heap-profile at program exit |
676 struct HeapProfileEndWriter { | 688 struct HeapProfileEndWriter { |
677 ~HeapProfileEndWriter() { HeapProfilerDump("Exiting"); } | 689 ~HeapProfileEndWriter() { HeapProfilerDump("Exiting"); } |
678 }; | 690 }; |
679 | 691 |
680 // We want to make sure tcmalloc is up and running before starting the profiler | 692 // We want to make sure tcmalloc is up and running before starting the profiler |
681 static const TCMallocGuard tcmalloc_initializer; | 693 static const TCMallocGuard tcmalloc_initializer; |
682 REGISTER_MODULE_INITIALIZER(heapprofiler, HeapProfilerInit()); | 694 REGISTER_MODULE_INITIALIZER(heapprofiler, HeapProfilerInit()); |
683 static HeapProfileEndWriter heap_profile_end_writer; | 695 static HeapProfileEndWriter heap_profile_end_writer; |
OLD | NEW |