Changeset 133119 in webkit
- Timestamp:
- Oct 31, 2012, 8:21:02 PM (13 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r133113 r133119 1 2012-10-31 Chris Evans <cevans@google.com> 2 3 RenderArena has a memory leak and poor efficiency 4 https://bugs.webkit.org/show_bug.cgi?id=100893 5 6 Reviewed by Eric Seidel. 7 8 1) Avoid memory leak that persists for the Document lifetime by 9 increasing recycled size buckets up to 1024. It was previously 400, 10 and sizeof(RenderNamedFlowThread) / sizeof(RenderSVGText) both blew this 11 quota. An assert was added to prevent this happening again. 12 13 2) Fix the size of the recyled size bucket array on 64-bit. We only 14 need 8 byte granularity on 64-bit, but we had 4. 15 16 3) Try and pass power-of-two sizes to the underlying malloc() call, so 17 that we're space efficient. We now take Arena metadata into account. 18 19 4) Double the default RenderArena size allocation to 8192 bytes. Even 20 for a render of a trivial text file, 4096 bytes is not enough to prevent 21 extra calls into the underlying malloc() for more arena pool. 22 23 * rendering/RenderArena.cpp: 24 (WebCore::RenderArena::RenderArena): Adjust arena size so that we pass on the page-sized multiple to the underlying malloc() implementation. 25 (WebCore::RenderArena::allocate): 26 (WebCore::RenderArena::free): Assert that the allocation size is handled by our recycling buckets. 27 * rendering/RenderArena.h: 28 (WebCore): Maintain free buckets up to 1024 bytes to avoid memory leak. 29 (RenderArena): Double the default allocation size and handle 64-bit systems more efficiently. 30 1 31 2012-10-31 Adam Barth <abarth@webkit.org> 2 32 -
trunk/Source/WebCore/rendering/RenderArena.cpp
r132970 r133119 71 71 , m_totalAllocated(0) 72 72 { 73 ASSERT(arenaSize > sizeof(Arena) + ARENA_ALIGN_MASK); 74 // The underlying Arena class allocates some metadata on top of our 75 // requested size. Factor this in so that we can get perfect power-of-two 76 // allocation sizes passed to the underlying malloc() call. 77 arenaSize -= (sizeof(Arena) + ARENA_ALIGN_MASK); 73 78 // Initialize the arena pool 74 79 INIT_ARENA_POOL(&m_pool, "RenderArena", arenaSize); … … 98 103 void* RenderArena::allocate(size_t size) 99 104 { 105 ASSERT(size <= gMaxRecycledSize - 32); 100 106 m_totalSize += size; 101 107 … … 112 118 return static_cast<char*>(block) + debugHeaderSize; 113 119 #else 114 void* result = 0;115 116 120 // Ensure we have correct alignment for pointers. Important for Tru64 117 121 size = ROUNDUP(size, sizeof(void*)); 118 122 119 // Check recyclers first 120 if (size < gMaxRecycledSize) { 121 const size_t index = size >> 2; 123 const size_t index = size >> kRecyclerShift; 122 124 123 result = m_recyclers[index]; 124 if (result) { 125 // Need to move to the next object 126 void* next = MaskPtr(*((void**)result), m_mask); 127 m_recyclers[index] = next; 128 } 125 void* result = m_recyclers[index]; 126 if (result) { 127 // Need to move to the next object 128 void* next = MaskPtr(*((void**)result), m_mask); 129 m_recyclers[index] = next; 129 130 } 130 131 … … 142 143 void RenderArena::free(size_t size, void* ptr) 143 144 { 145 ASSERT(size <= gMaxRecycledSize - 32); 144 146 m_totalSize -= size; 145 147 … … 159 161 size = ROUNDUP(size, sizeof(void*)); 160 162 161 // See if it's a size that we recycle 162 if (size < gMaxRecycledSize) { 163 const size_t index = size >> 2; 164 void* currentTop = m_recyclers[index]; 165 m_recyclers[index] = ptr; 166 *((void**)ptr) = MaskPtr(currentTop, m_mask); 167 } 163 const size_t index = size >> kRecyclerShift; 164 void* currentTop = m_recyclers[index]; 165 m_recyclers[index] = ptr; 166 *((void**)ptr) = MaskPtr(currentTop, m_mask); 168 167 #endif 169 168 } -
trunk/Source/WebCore/rendering/RenderArena.h
r132970 r133119 42 42 namespace WebCore { 43 43 44 static const size_t gMaxRecycledSize = 400;44 static const size_t gMaxRecycledSize = 1024; 45 45 46 46 class RenderArena { 47 47 WTF_MAKE_NONCOPYABLE(RenderArena); WTF_MAKE_FAST_ALLOCATED; 48 48 public: 49 RenderArena(unsigned arenaSize = 4096);49 RenderArena(unsigned arenaSize = 8192); 50 50 ~RenderArena(); 51 51 … … 63 63 // The mask used to secure the recycled freelist pointers. 64 64 uintptr_t m_mask; 65 // The recycler array is sparse with the indices being multiples of 4, 66 // i.e., 0, 4, 8, 12, 16, 20, ... 67 void* m_recyclers[gMaxRecycledSize >> 2]; 65 // The recycler array is sparse with the indices being multiples of the 66 // rounding size, sizeof(void*), i.e., 0, 4, 8, 12, 16, 20, ... on 32-bit. 67 static const size_t kRecyclerShift = (sizeof(void*) == 8) ? 3 : 2; 68 void* m_recyclers[gMaxRecycledSize >> kRecyclerShift]; 68 69 69 70 size_t m_totalSize;
Note:
See TracChangeset
for help on using the changeset viewer.