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 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 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 |
178 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 | 179 static int64 last_dump_time = 0; // The time of the last dump |
180 | 180 |
181 static HeapProfileTable* heap_profile = NULL; // the heap profile table | 181 static HeapProfileTable* heap_profile = NULL; // the heap profile table |
182 | 182 |
183 //---------------------------------------------------------------------- | 183 //---------------------------------------------------------------------- |
184 // Profile generation | 184 // Profile generation |
185 //---------------------------------------------------------------------- | 185 //---------------------------------------------------------------------- |
186 | 186 |
187 enum AddOrRemove { ADD, REMOVE }; | |
188 | |
189 // Add or remove all MMap-allocated regions to/from *heap_profile. | |
190 // Assumes heap_lock is held. | |
191 static void AddRemoveMMapDataLocked(AddOrRemove mode) { | |
192 RAW_DCHECK(heap_lock.IsHeld(), ""); | |
193 if (!FLAGS_mmap_profile || !is_on) return; | |
194 // MemoryRegionMap maintained all the data we need for all | |
195 // mmap-like allocations, so we just use it here: | |
196 MemoryRegionMap::LockHolder l; | |
197 for (MemoryRegionMap::RegionIterator r = MemoryRegionMap::BeginRegionLocked(); | |
198 r != MemoryRegionMap::EndRegionLocked(); ++r) { | |
199 if (mode == ADD) { | |
200 heap_profile->RecordAllocWithStack( | |
201 reinterpret_cast<const void*>(r->start_addr), | |
202 r->end_addr - r->start_addr, | |
203 r->call_stack_depth, r->call_stack); | |
204 } else { | |
205 heap_profile->RecordFree(reinterpret_cast<void*>(r->start_addr)); | |
206 } | |
207 } | |
208 } | |
209 | |
210 // Input must be a buffer of size at least 1MB. | 187 // Input must be a buffer of size at least 1MB. |
211 static char* DoGetHeapProfileLocked(char* buf, int buflen) { | 188 static char* DoGetHeapProfileLocked(char* buf, int buflen) { |
212 // We used to be smarter about estimating the required memory and | 189 // We used to be smarter about estimating the required memory and |
213 // then capping it to 1MB and generating the profile into that. | 190 // then capping it to 1MB and generating the profile into that. |
214 if (buf == NULL || buflen < 1) | 191 if (buf == NULL || buflen < 1) |
215 return NULL; | 192 return NULL; |
216 | 193 |
217 RAW_DCHECK(heap_lock.IsHeld(), ""); | 194 RAW_DCHECK(heap_lock.IsHeld(), ""); |
218 int bytes_written = 0; | 195 int bytes_written = 0; |
219 if (is_on) { | 196 if (is_on) { |
220 HeapProfileTable::Stats const stats = heap_profile->total(); | 197 if (FLAGS_mmap_profile) { |
221 (void)stats; // avoid an unused-variable warning in non-debug mode. | 198 heap_profile->RefreshMMapData(); |
222 AddRemoveMMapDataLocked(ADD); | 199 } |
223 bytes_written = heap_profile->FillOrderedProfile(buf, buflen - 1); | 200 bytes_written = heap_profile->FillOrderedProfile(buf, buflen - 1); |
224 // FillOrderedProfile should not reduce the set of active mmap-ed regions, | 201 if (FLAGS_mmap_profile) { |
225 // hence MemoryRegionMap will let us remove everything we've added above: | 202 heap_profile->ClearMMapData(); |
226 AddRemoveMMapDataLocked(REMOVE); | 203 } |
227 RAW_DCHECK(stats.Equivalent(heap_profile->total()), ""); | |
228 // if this fails, we somehow removed by AddRemoveMMapDataLocked | |
229 // more than we have added. | |
230 } | 204 } |
231 buf[bytes_written] = '\0'; | 205 buf[bytes_written] = '\0'; |
232 RAW_DCHECK(bytes_written == strlen(buf), ""); | 206 RAW_DCHECK(bytes_written == strlen(buf), ""); |
233 | 207 |
234 return buf; | 208 return buf; |
235 } | 209 } |
236 | 210 |
237 extern "C" char* GetHeapProfile() { | 211 extern "C" char* GetHeapProfile() { |
238 // Use normal malloc: we return the profile to the user to free it: | 212 // Use normal malloc: we return the profile to the user to free it: |
239 char* buffer = reinterpret_cast<char*>(malloc(kProfileBufferSize)); | 213 char* buffer = reinterpret_cast<char*>(malloc(kProfileBufferSize)); |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 | 561 |
588 // class used for finalization -- dumps the heap-profile at program exit | 562 // class used for finalization -- dumps the heap-profile at program exit |
589 struct HeapProfileEndWriter { | 563 struct HeapProfileEndWriter { |
590 ~HeapProfileEndWriter() { HeapProfilerDump("Exiting"); } | 564 ~HeapProfileEndWriter() { HeapProfilerDump("Exiting"); } |
591 }; | 565 }; |
592 | 566 |
593 // We want to make sure tcmalloc is up and running before starting the profiler | 567 // We want to make sure tcmalloc is up and running before starting the profiler |
594 static const TCMallocGuard tcmalloc_initializer; | 568 static const TCMallocGuard tcmalloc_initializer; |
595 REGISTER_MODULE_INITIALIZER(heapprofiler, HeapProfilerInit()); | 569 REGISTER_MODULE_INITIALIZER(heapprofiler, HeapProfilerInit()); |
596 static HeapProfileEndWriter heap_profile_end_writer; | 570 static HeapProfileEndWriter heap_profile_end_writer; |
OLD | NEW |