Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Side by Side Diff: third_party/tcmalloc/chromium/src/heap-profiler.cc

Issue 9323026: [NOT TO COMMIT!] r109: Diff of the current tcmalloc from the original google-perftools r109. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 "If non-zero, dump heap profiling information once every " 100 "If non-zero, dump heap profiling information once every "
101 "specified number of bytes deallocated by the program " 101 "specified number of bytes deallocated by the program "
102 "since the last dump."); 102 "since the last dump.");
103 // We could also add flags that report whenever inuse_bytes changes by 103 // We could also add flags that report whenever inuse_bytes changes by
104 // X or -X, but there hasn't been a need for that yet, so we haven't. 104 // X or -X, but there hasn't been a need for that yet, so we haven't.
105 DEFINE_int64(heap_profile_inuse_interval, 105 DEFINE_int64(heap_profile_inuse_interval,
106 EnvToInt64("HEAP_PROFILE_INUSE_INTERVAL", 100 << 20 /*100MB*/), 106 EnvToInt64("HEAP_PROFILE_INUSE_INTERVAL", 100 << 20 /*100MB*/),
107 "If non-zero, dump heap profiling information whenever " 107 "If non-zero, dump heap profiling information whenever "
108 "the high-water memory usage mark increases by the specified " 108 "the high-water memory usage mark increases by the specified "
109 "number of bytes."); 109 "number of bytes.");
110 DEFINE_int64(heap_profile_time_interval,
111 EnvToInt64("HEAP_PROFILE_TIME_INTERVAL", 0),
112 "If non-zero, dump heap profiling information once every "
113 "specified number of seconds since the last dump.");
110 DEFINE_bool(mmap_log, 114 DEFINE_bool(mmap_log,
111 EnvToBool("HEAP_PROFILE_MMAP_LOG", false), 115 EnvToBool("HEAP_PROFILE_MMAP_LOG", false),
112 "Should mmap/munmap calls be logged?"); 116 "Should mmap/munmap calls be logged?");
113 DEFINE_bool(mmap_profile, 117 DEFINE_bool(mmap_profile,
114 EnvToBool("HEAP_PROFILE_MMAP", false), 118 EnvToBool("HEAP_PROFILE_MMAP", false),
115 "If heap-profiling is on, also profile mmap, mremap, and sbrk)"); 119 "If heap-profiling is on, also profile mmap, mremap, and sbrk)");
116 DEFINE_bool(only_mmap_profile, 120 DEFINE_bool(only_mmap_profile,
117 EnvToBool("HEAP_PROFILE_ONLY_MMAP", false), 121 EnvToBool("HEAP_PROFILE_ONLY_MMAP", false),
118 "If heap-profiling is on, only profile mmap, mremap, and sbrk; " 122 "If heap-profiling is on, only profile mmap, mremap, and sbrk; "
119 "do not profile malloc/new/etc"); 123 "do not profile malloc/new/etc");
(...skipping 18 matching lines...) Expand all
138 static LowLevelAlloc::Arena *heap_profiler_memory; 142 static LowLevelAlloc::Arena *heap_profiler_memory;
139 143
140 static void* ProfilerMalloc(size_t bytes) { 144 static void* ProfilerMalloc(size_t bytes) {
141 return LowLevelAlloc::AllocWithArena(bytes, heap_profiler_memory); 145 return LowLevelAlloc::AllocWithArena(bytes, heap_profiler_memory);
142 } 146 }
143 static void ProfilerFree(void* p) { 147 static void ProfilerFree(void* p) {
144 LowLevelAlloc::Free(p); 148 LowLevelAlloc::Free(p);
145 } 149 }
146 150
147 // We use buffers of this size in DoGetHeapProfile. 151 // We use buffers of this size in DoGetHeapProfile.
148 static const int kProfileBufferSize = 1 << 20; 152 // The size is 1 << 20 in the original google-perftools. Changed it to
153 // 5 << 20 since a larger buffer is requried for deeper profiling in Chromium.
154 // The buffer is allocated only when the environment variable HEAPPROFILE is
155 // specified to dump heap information.
156 static const int kProfileBufferSize = 5 << 20;
149 157
150 // This is a last-ditch buffer we use in DumpProfileLocked in case we 158 // This is a last-ditch buffer we use in DumpProfileLocked in case we
151 // can't allocate more memory from ProfilerMalloc. We expect this 159 // can't allocate more memory from ProfilerMalloc. We expect this
152 // will be used by HeapProfileEndWriter when the application has to 160 // will be used by HeapProfileEndWriter when the application has to
153 // exit due to out-of-memory. This buffer is allocated in 161 // exit due to out-of-memory. This buffer is allocated in
154 // HeapProfilerStart. Access to this must be protected by heap_lock. 162 // HeapProfilerStart. Access to this must be protected by heap_lock.
155 static char* global_profiler_buffer = NULL; 163 static char* global_profiler_buffer = NULL;
156 164
157 165
158 //---------------------------------------------------------------------- 166 //----------------------------------------------------------------------
159 // Profiling control/state data 167 // Profiling control/state data
160 //---------------------------------------------------------------------- 168 //----------------------------------------------------------------------
161 169
162 // Access to all of these is protected by heap_lock. 170 // Access to all of these is protected by heap_lock.
163 static bool is_on = false; // If are on as a subsytem. 171 static bool is_on = false; // If are on as a subsytem.
164 static bool dumping = false; // Dumping status to prevent recursion 172 static bool dumping = false; // Dumping status to prevent recursion
165 static char* filename_prefix = NULL; // Prefix used for profile file names 173 static char* filename_prefix = NULL; // Prefix used for profile file names
166 // (NULL if no need for dumping yet) 174 // (NULL if no need for dumping yet)
167 static int dump_count = 0; // How many dumps so far 175 static int dump_count = 0; // How many dumps so far
168 static int64 last_dump_alloc = 0; // alloc_size when did we last dump 176 static int64 last_dump_alloc = 0; // alloc_size when did we last dump
169 static int64 last_dump_free = 0; // free_size when did we last dump 177 static int64 last_dump_free = 0; // free_size when did we last dump
170 static int64 high_water_mark = 0; // In-use-bytes at last high-water dump 178 static int64 high_water_mark = 0; // In-use-bytes at last high-water dump
179 static int64 last_dump_time = 0; // The time of the last dump
171 180
172 static HeapProfileTable* heap_profile = NULL; // the heap profile table 181 static HeapProfileTable* heap_profile = NULL; // the heap profile table
173 182
174 //---------------------------------------------------------------------- 183 //----------------------------------------------------------------------
175 // Profile generation 184 // Profile generation
176 //---------------------------------------------------------------------- 185 //----------------------------------------------------------------------
177 186
178 enum AddOrRemove { ADD, REMOVE }; 187 enum AddOrRemove { ADD, REMOVE };
179 188
180 // Add or remove all MMap-allocated regions to/from *heap_profile. 189 // Add or remove all MMap-allocated regions to/from *heap_profile.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 RAW_DCHECK(is_on, ""); 251 RAW_DCHECK(is_on, "");
243 RAW_DCHECK(!dumping, ""); 252 RAW_DCHECK(!dumping, "");
244 253
245 if (filename_prefix == NULL) return; // we do not yet need dumping 254 if (filename_prefix == NULL) return; // we do not yet need dumping
246 255
247 dumping = true; 256 dumping = true;
248 257
249 // Make file name 258 // Make file name
250 char file_name[1000]; 259 char file_name[1000];
251 dump_count++; 260 dump_count++;
252 snprintf(file_name, sizeof(file_name), "%s.%04d%s", 261 snprintf(file_name, sizeof(file_name), "%s.%05d.%04d%s",
253 filename_prefix, dump_count, HeapProfileTable::kFileExt); 262 filename_prefix, getpid(), dump_count, HeapProfileTable::kFileExt);
254 263
255 // Dump the profile 264 // Dump the profile
256 RAW_VLOG(0, "Dumping heap profile to %s (%s)", file_name, reason); 265 RAW_VLOG(0, "Dumping heap profile to %s (%s)", file_name, reason);
257 // We must use file routines that don't access memory, since we hold 266 // We must use file routines that don't access memory, since we hold
258 // a memory lock now. 267 // a memory lock now.
259 RawFD fd = RawOpenForWriting(file_name); 268 RawFD fd = RawOpenForWriting(file_name);
260 if (fd == kIllegalRawFD) { 269 if (fd == kIllegalRawFD) {
261 RAW_LOG(ERROR, "Failed dumping heap profile to %s", file_name); 270 RAW_LOG(ERROR, "Failed dumping heap profile to %s", file_name);
262 dumping = false; 271 dumping = false;
263 return; 272 return;
(...skipping 19 matching lines...) Expand all
283 //---------------------------------------------------------------------- 292 //----------------------------------------------------------------------
284 293
285 // Dump a profile after either an allocation or deallocation, if 294 // Dump a profile after either an allocation or deallocation, if
286 // the memory use has changed enough since the last dump. 295 // the memory use has changed enough since the last dump.
287 static void MaybeDumpProfileLocked() { 296 static void MaybeDumpProfileLocked() {
288 if (!dumping) { 297 if (!dumping) {
289 const HeapProfileTable::Stats& total = heap_profile->total(); 298 const HeapProfileTable::Stats& total = heap_profile->total();
290 const int64 inuse_bytes = total.alloc_size - total.free_size; 299 const int64 inuse_bytes = total.alloc_size - total.free_size;
291 bool need_to_dump = false; 300 bool need_to_dump = false;
292 char buf[128]; 301 char buf[128];
302 int64 current_time = time(NULL);
293 if (FLAGS_heap_profile_allocation_interval > 0 && 303 if (FLAGS_heap_profile_allocation_interval > 0 &&
294 total.alloc_size >= 304 total.alloc_size >=
295 last_dump_alloc + FLAGS_heap_profile_allocation_interval) { 305 last_dump_alloc + FLAGS_heap_profile_allocation_interval) {
296 snprintf(buf, sizeof(buf), ("%"PRId64" MB allocated cumulatively, " 306 snprintf(buf, sizeof(buf), ("%"PRId64" MB allocated cumulatively, "
297 "%"PRId64" MB currently in use"), 307 "%"PRId64" MB currently in use"),
298 total.alloc_size >> 20, inuse_bytes >> 20); 308 total.alloc_size >> 20, inuse_bytes >> 20);
299 need_to_dump = true; 309 need_to_dump = true;
300 } else if (FLAGS_heap_profile_deallocation_interval > 0 && 310 } else if (FLAGS_heap_profile_deallocation_interval > 0 &&
301 total.free_size >= 311 total.free_size >=
302 last_dump_free + FLAGS_heap_profile_deallocation_interval) { 312 last_dump_free + FLAGS_heap_profile_deallocation_interval) {
303 snprintf(buf, sizeof(buf), ("%"PRId64" MB freed cumulatively, " 313 snprintf(buf, sizeof(buf), ("%"PRId64" MB freed cumulatively, "
304 "%"PRId64" MB currently in use"), 314 "%"PRId64" MB currently in use"),
305 total.free_size >> 20, inuse_bytes >> 20); 315 total.free_size >> 20, inuse_bytes >> 20);
306 need_to_dump = true; 316 need_to_dump = true;
307 } else if (FLAGS_heap_profile_inuse_interval > 0 && 317 } else if (FLAGS_heap_profile_inuse_interval > 0 &&
308 inuse_bytes > 318 inuse_bytes >
309 high_water_mark + FLAGS_heap_profile_inuse_interval) { 319 high_water_mark + FLAGS_heap_profile_inuse_interval) {
310 snprintf(buf, sizeof(buf), "%"PRId64" MB currently in use", 320 snprintf(buf, sizeof(buf), "%"PRId64" MB currently in use",
311 inuse_bytes >> 20); 321 inuse_bytes >> 20);
312 need_to_dump = true; 322 need_to_dump = true;
323 } else if (FLAGS_heap_profile_time_interval > 0 &&
324 current_time - last_dump_time >=
325 FLAGS_heap_profile_time_interval) {
326 snprintf(buf, sizeof(buf), "%d sec since the last dump",
327 current_time - last_dump_time);
328 need_to_dump = true;
329 last_dump_time = current_time;
313 } 330 }
314 if (need_to_dump) { 331 if (need_to_dump) {
315 DumpProfileLocked(buf); 332 DumpProfileLocked(buf);
316 333
317 last_dump_alloc = total.alloc_size; 334 last_dump_alloc = total.alloc_size;
318 last_dump_free = total.free_size; 335 last_dump_free = total.free_size;
319 if (inuse_bytes > high_water_mark) 336 if (inuse_bytes > high_water_mark)
320 high_water_mark = inuse_bytes; 337 high_water_mark = inuse_bytes;
321 } 338 }
322 } 339 }
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 // in pretty-printing of NULL as "nil". 421 // in pretty-printing of NULL as "nil".
405 // TODO(maxim): instead should use a safe snprintf reimplementation 422 // TODO(maxim): instead should use a safe snprintf reimplementation
406 RAW_LOG(INFO, "munmap(start=0x%"PRIxPTR", len=%"PRIuS")", 423 RAW_LOG(INFO, "munmap(start=0x%"PRIxPTR", len=%"PRIuS")",
407 (uintptr_t) ptr, size); 424 (uintptr_t) ptr, size);
408 #ifdef TODO_REENABLE_STACK_TRACING 425 #ifdef TODO_REENABLE_STACK_TRACING
409 DumpStackTrace(1, RawInfoStackDumper, NULL); 426 DumpStackTrace(1, RawInfoStackDumper, NULL);
410 #endif 427 #endif
411 } 428 }
412 } 429 }
413 430
414 static void SbrkHook(const void* result, ptrdiff_t increment) { 431 static void SbrkHook(const void* result, std::ptrdiff_t increment) {
415 if (FLAGS_mmap_log) { // log it 432 if (FLAGS_mmap_log) { // log it
416 RAW_LOG(INFO, "sbrk(inc=%"PRIdS") = 0x%"PRIxPTR"", 433 RAW_LOG(INFO, "sbrk(inc=%"PRIdS") = 0x%"PRIxPTR"",
417 increment, (uintptr_t) result); 434 increment, (uintptr_t) result);
418 #ifdef TODO_REENABLE_STACK_TRACING 435 #ifdef TODO_REENABLE_STACK_TRACING
419 DumpStackTrace(1, RawInfoStackDumper, NULL); 436 DumpStackTrace(1, RawInfoStackDumper, NULL);
420 #endif 437 #endif
421 } 438 }
422 } 439 }
423 440
424 //---------------------------------------------------------------------- 441 //----------------------------------------------------------------------
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 // heap profile even if the application runs out of memory. 480 // heap profile even if the application runs out of memory.
464 global_profiler_buffer = 481 global_profiler_buffer =
465 reinterpret_cast<char*>(ProfilerMalloc(kProfileBufferSize)); 482 reinterpret_cast<char*>(ProfilerMalloc(kProfileBufferSize));
466 483
467 heap_profile = new(ProfilerMalloc(sizeof(HeapProfileTable))) 484 heap_profile = new(ProfilerMalloc(sizeof(HeapProfileTable)))
468 HeapProfileTable(ProfilerMalloc, ProfilerFree); 485 HeapProfileTable(ProfilerMalloc, ProfilerFree);
469 486
470 last_dump_alloc = 0; 487 last_dump_alloc = 0;
471 last_dump_free = 0; 488 last_dump_free = 0;
472 high_water_mark = 0; 489 high_water_mark = 0;
490 last_dump_time = 0;
473 491
474 // We do not reset dump_count so if the user does a sequence of 492 // We do not reset dump_count so if the user does a sequence of
475 // HeapProfilerStart/HeapProfileStop, we will get a continuous 493 // HeapProfilerStart/HeapProfileStop, we will get a continuous
476 // sequence of profiles. 494 // sequence of profiles.
477 495
478 if (FLAGS_only_mmap_profile == false) { 496 if (FLAGS_only_mmap_profile == false) {
479 // Now set the hooks that capture new/delete and malloc/free. 497 // Now set the hooks that capture new/delete and malloc/free.
480 RAW_CHECK(MallocHook::AddNewHook(&NewHook), ""); 498 RAW_CHECK(MallocHook::AddNewHook(&NewHook), "");
481 RAW_CHECK(MallocHook::AddDeleteHook(&DeleteHook), ""); 499 RAW_CHECK(MallocHook::AddDeleteHook(&DeleteHook), "");
482 } 500 }
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 587
570 // class used for finalization -- dumps the heap-profile at program exit 588 // class used for finalization -- dumps the heap-profile at program exit
571 struct HeapProfileEndWriter { 589 struct HeapProfileEndWriter {
572 ~HeapProfileEndWriter() { HeapProfilerDump("Exiting"); } 590 ~HeapProfileEndWriter() { HeapProfilerDump("Exiting"); }
573 }; 591 };
574 592
575 // We want to make sure tcmalloc is up and running before starting the profiler 593 // We want to make sure tcmalloc is up and running before starting the profiler
576 static const TCMallocGuard tcmalloc_initializer; 594 static const TCMallocGuard tcmalloc_initializer;
577 REGISTER_MODULE_INITIALIZER(heapprofiler, HeapProfilerInit()); 595 REGISTER_MODULE_INITIALIZER(heapprofiler, HeapProfilerInit());
578 static HeapProfileEndWriter heap_profile_end_writer; 596 static HeapProfileEndWriter heap_profile_end_writer;
OLDNEW
« no previous file with comments | « third_party/tcmalloc/chromium/src/heap-profile-table.cc ('k') | third_party/tcmalloc/chromium/src/linux_shadow_stacks.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698