| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. |
| 3 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. | 3 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. 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 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 25 */ | 25 */ |
| 26 | 26 |
| 27 #include "platform/SharedBuffer.h" | 27 #include "platform/SharedBuffer.h" |
| 28 | 28 |
| 29 #include "platform/web_process_memory_dump.h" | 29 #include "platform/web_process_memory_dump.h" |
| 30 #include "wtf/text/UTF8.h" | 30 #include "wtf/text/UTF8.h" |
| 31 #include "wtf/text/Unicode.h" | 31 #include "wtf/text/Unicode.h" |
| 32 | 32 |
| 33 #undef SHARED_BUFFER_STATS | |
| 34 | |
| 35 #ifdef SHARED_BUFFER_STATS | |
| 36 #include "public/platform/Platform.h" | |
| 37 #include "public/platform/WebTaskRunner.h" | |
| 38 #include "public/platform/WebTraceLocation.h" | |
| 39 #include "wtf/DataLog.h" | |
| 40 #include <set> | |
| 41 #endif | |
| 42 | |
| 43 namespace blink { | 33 namespace blink { |
| 44 | 34 |
| 45 static inline size_t segmentIndex(size_t position) | 35 static inline size_t segmentIndex(size_t position) |
| 46 { | 36 { |
| 47 return position / SharedBuffer::kSegmentSize; | 37 return position / SharedBuffer::kSegmentSize; |
| 48 } | 38 } |
| 49 | 39 |
| 50 static inline size_t offsetInSegment(size_t position) | 40 static inline size_t offsetInSegment(size_t position) |
| 51 { | 41 { |
| 52 return position % SharedBuffer::kSegmentSize; | 42 return position % SharedBuffer::kSegmentSize; |
| 53 } | 43 } |
| 54 | 44 |
| 55 static inline char* allocateSegment() | 45 static inline char* allocateSegment() |
| 56 { | 46 { |
| 57 return static_cast<char*>(WTF::Partitions::fastMalloc(SharedBuffer::kSegment
Size, "blink::SharedBuffer")); | 47 return static_cast<char*>(WTF::Partitions::fastMalloc(SharedBuffer::kSegment
Size, "blink::SharedBuffer")); |
| 58 } | 48 } |
| 59 | 49 |
| 60 static inline void freeSegment(char* p) | 50 static inline void freeSegment(char* p) |
| 61 { | 51 { |
| 62 WTF::Partitions::fastFree(p); | 52 WTF::Partitions::fastFree(p); |
| 63 } | 53 } |
| 64 | 54 |
| 65 #ifdef SHARED_BUFFER_STATS | |
| 66 | |
| 67 static Mutex& statsMutex() | |
| 68 { | |
| 69 DEFINE_STATIC_LOCAL(Mutex, mutex, ()); | |
| 70 return mutex; | |
| 71 } | |
| 72 | |
| 73 static std::set<SharedBuffer*>& liveBuffers() | |
| 74 { | |
| 75 // Use std::set instead of WTF::HashSet to avoid increasing PartitionAlloc | |
| 76 // memory usage. | |
| 77 DEFINE_STATIC_LOCAL(std::set<SharedBuffer*>, buffers, ()); | |
| 78 return buffers; | |
| 79 } | |
| 80 | |
| 81 static bool sizeComparator(SharedBuffer* a, SharedBuffer* b) | |
| 82 { | |
| 83 return a->size() > b->size(); | |
| 84 } | |
| 85 | |
| 86 static CString snippetForBuffer(SharedBuffer* sharedBuffer) | |
| 87 { | |
| 88 const size_t kMaxSnippetLength = 64; | |
| 89 char* snippet = 0; | |
| 90 size_t snippetLength = std::min(sharedBuffer->size(), kMaxSnippetLength); | |
| 91 CString result = CString::newUninitialized(snippetLength, snippet); | |
| 92 | |
| 93 const char* segment; | |
| 94 size_t offset = 0; | |
| 95 while (size_t segmentLength = sharedBuffer->getSomeDataInternal(segment, off
set)) { | |
| 96 size_t length = std::min(segmentLength, snippetLength - offset); | |
| 97 memcpy(snippet + offset, segment, length); | |
| 98 offset += segmentLength; | |
| 99 if (offset >= snippetLength) | |
| 100 break; | |
| 101 } | |
| 102 | |
| 103 for (size_t i = 0; i < snippetLength; ++i) { | |
| 104 if (!isASCIIPrintable(snippet[i])) | |
| 105 snippet[i] = '?'; | |
| 106 } | |
| 107 | |
| 108 return result; | |
| 109 } | |
| 110 | |
| 111 static void printStats() | |
| 112 { | |
| 113 MutexLocker locker(statsMutex()); | |
| 114 Vector<SharedBuffer*> buffers; | |
| 115 for (auto* buffer : liveBuffers()) | |
| 116 buffers.append(buffer); | |
| 117 std::sort(buffers.begin(), buffers.end(), sizeComparator); | |
| 118 | |
| 119 dataLogF("---- Shared Buffer Stats ----\n"); | |
| 120 for (size_t i = 0; i < buffers.size() && i < 64; ++i) { | |
| 121 CString snippet = snippetForBuffer(buffers[i]); | |
| 122 dataLogF("Buffer size=%8u %s\n", buffers[i]->size(), snippet.data()); | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 static void didCreateSharedBuffer(SharedBuffer* buffer) | |
| 127 { | |
| 128 MutexLocker locker(statsMutex()); | |
| 129 liveBuffers().insert(buffer); | |
| 130 | |
| 131 Platform::current()->mainThread()->taskRunner()->postTask(BLINK_FROM_HERE, W
TF::bind(&printStats)); | |
| 132 } | |
| 133 | |
| 134 static void willDestroySharedBuffer(SharedBuffer* buffer) | |
| 135 { | |
| 136 MutexLocker locker(statsMutex()); | |
| 137 liveBuffers().erase(buffer); | |
| 138 } | |
| 139 | |
| 140 #endif | |
| 141 | |
| 142 SharedBuffer::SharedBuffer() | 55 SharedBuffer::SharedBuffer() |
| 143 : m_size(0) | 56 : m_size(0) |
| 144 , m_buffer(PurgeableVector::NotPurgeable) | 57 , m_buffer(PurgeableVector::NotPurgeable) |
| 145 { | 58 { |
| 146 #ifdef SHARED_BUFFER_STATS | |
| 147 didCreateSharedBuffer(this); | |
| 148 #endif | |
| 149 } | 59 } |
| 150 | 60 |
| 151 SharedBuffer::SharedBuffer(size_t size) | 61 SharedBuffer::SharedBuffer(size_t size) |
| 152 : m_size(size) | 62 : m_size(size) |
| 153 , m_buffer(PurgeableVector::NotPurgeable) | 63 , m_buffer(PurgeableVector::NotPurgeable) |
| 154 { | 64 { |
| 155 m_buffer.reserveCapacity(size); | 65 m_buffer.reserveCapacity(size); |
| 156 m_buffer.grow(size); | 66 m_buffer.grow(size); |
| 157 #ifdef SHARED_BUFFER_STATS | |
| 158 didCreateSharedBuffer(this); | |
| 159 #endif | |
| 160 } | 67 } |
| 161 | 68 |
| 162 SharedBuffer::SharedBuffer(const char* data, size_t size) | 69 SharedBuffer::SharedBuffer(const char* data, size_t size) |
| 163 : m_size(0) | 70 : m_size(0) |
| 164 , m_buffer(PurgeableVector::NotPurgeable) | 71 , m_buffer(PurgeableVector::NotPurgeable) |
| 165 { | 72 { |
| 166 appendInternal(data, size); | 73 appendInternal(data, size); |
| 167 | |
| 168 #ifdef SHARED_BUFFER_STATS | |
| 169 didCreateSharedBuffer(this); | |
| 170 #endif | |
| 171 } | 74 } |
| 172 | 75 |
| 173 SharedBuffer::SharedBuffer(const char* data, size_t size, PurgeableVector::Purge
ableOption purgeable) | 76 SharedBuffer::SharedBuffer(const char* data, size_t size, PurgeableVector::Purge
ableOption purgeable) |
| 174 : m_size(0) | 77 : m_size(0) |
| 175 , m_buffer(purgeable) | 78 , m_buffer(purgeable) |
| 176 { | 79 { |
| 177 appendInternal(data, size); | 80 appendInternal(data, size); |
| 178 | |
| 179 #ifdef SHARED_BUFFER_STATS | |
| 180 didCreateSharedBuffer(this); | |
| 181 #endif | |
| 182 } | 81 } |
| 183 | 82 |
| 184 SharedBuffer::SharedBuffer(const unsigned char* data, size_t size) | 83 SharedBuffer::SharedBuffer(const unsigned char* data, size_t size) |
| 185 : m_size(0) | 84 : m_size(0) |
| 186 , m_buffer(PurgeableVector::NotPurgeable) | 85 , m_buffer(PurgeableVector::NotPurgeable) |
| 187 { | 86 { |
| 188 appendInternal(reinterpret_cast<const char*>(data), size); | 87 appendInternal(reinterpret_cast<const char*>(data), size); |
| 189 | |
| 190 #ifdef SHARED_BUFFER_STATS | |
| 191 didCreateSharedBuffer(this); | |
| 192 #endif | |
| 193 } | 88 } |
| 194 | 89 |
| 195 SharedBuffer::~SharedBuffer() | 90 SharedBuffer::~SharedBuffer() |
| 196 { | 91 { |
| 197 clear(); | 92 clear(); |
| 198 | |
| 199 #ifdef SHARED_BUFFER_STATS | |
| 200 willDestroySharedBuffer(this); | |
| 201 #endif | |
| 202 } | 93 } |
| 203 | 94 |
| 204 PassRefPtr<SharedBuffer> SharedBuffer::adoptVector(Vector<char>& vector) | 95 PassRefPtr<SharedBuffer> SharedBuffer::adoptVector(Vector<char>& vector) |
| 205 { | 96 { |
| 206 RefPtr<SharedBuffer> buffer = create(); | 97 RefPtr<SharedBuffer> buffer = create(); |
| 207 buffer->m_buffer.adopt(vector); | 98 buffer->m_buffer.adopt(vector); |
| 208 buffer->m_size = buffer->m_buffer.size(); | 99 buffer->m_size = buffer->m_buffer.size(); |
| 209 return buffer.release(); | 100 return buffer.release(); |
| 210 } | 101 } |
| 211 | 102 |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 // If there is data in the segments, then it should have been allocated | 305 // If there is data in the segments, then it should have been allocated |
| 415 // using fastMalloc. | 306 // using fastMalloc. |
| 416 const String dataDumpName = dumpPrefix + "/segments"; | 307 const String dataDumpName = dumpPrefix + "/segments"; |
| 417 auto dump = memoryDump->createMemoryAllocatorDump(dataDumpName); | 308 auto dump = memoryDump->createMemoryAllocatorDump(dataDumpName); |
| 418 dump->addScalar("size", "bytes", m_size); | 309 dump->addScalar("size", "bytes", m_size); |
| 419 memoryDump->addSuballocation(dump->guid(), String(WTF::Partitions::kAllo
catedObjectPoolName)); | 310 memoryDump->addSuballocation(dump->guid(), String(WTF::Partitions::kAllo
catedObjectPoolName)); |
| 420 } | 311 } |
| 421 } | 312 } |
| 422 | 313 |
| 423 } // namespace blink | 314 } // namespace blink |
| OLD | NEW |