From 5776508126534db2af97d560588e7046e745df65 Mon Sep 17 00:00:00 2001 From: fmalita Date: Fri, 30 Sep 2016 13:34:19 -0700 Subject: Add a SkRWBuffer reserve mechanism Currently, Chromium stores segmented data in a SharedBuffer and appends to SkRWBuffer one segment at a time: const char* segment = 0; for (size_t length = data->getSomeData(segment, m_rwBuffer->size()); length; length = data->getSomeData(segment, m_rwBuffer->size())) { m_rwBuffer->append(segment, length, remaining); } This can yield a bunch of just-above-4k allocations => wasted RAM due to internal fragmentation. Ideally, we'd want a SkRWBuffer::reserve(size_t bytes) API, but the current internals don't support that trivially. Alternatively, the caller can pass a reserve hint at append() time. BUG=chromium:651698 R=scroggo@google.com,reed@google.com GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2385803002 Review-Url: https://codereview.chromium.org/2385803002 --- include/core/SkRWBuffer.h | 10 +++++++++- src/core/SkRWBuffer.cpp | 6 +++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/core/SkRWBuffer.h b/include/core/SkRWBuffer.h index 9626d28df9..451933f353 100644 --- a/include/core/SkRWBuffer.h +++ b/include/core/SkRWBuffer.h @@ -79,7 +79,15 @@ public: ~SkRWBuffer(); size_t size() const { return fTotalUsed; } - void append(const void* buffer, size_t length); + + /** + * Append |length| bytes from |buffer|. + * + * If the caller knows in advance how much more data they are going to append, they can + * pass a |reserve| hint (representing the number of upcoming bytes *in addition* to the + * current append), to minimize the number of internal allocations. + */ + void append(const void* buffer, size_t length, size_t reserve = 0); SkROBuffer* newRBufferSnapshot() const; SkStreamAsset* newStreamSnapshot() const; diff --git a/src/core/SkRWBuffer.cpp b/src/core/SkRWBuffer.cpp index 41f1a287d2..e69070b5f9 100644 --- a/src/core/SkRWBuffer.cpp +++ b/src/core/SkRWBuffer.cpp @@ -199,7 +199,7 @@ SkRWBuffer::~SkRWBuffer() { // next, since our reader will be using fCapacity (min'd against its total available) to know how // many bytes to read from a given block. // -void SkRWBuffer::append(const void* src, size_t length) { +void SkRWBuffer::append(const void* src, size_t length, size_t reserve) { this->validate(); if (0 == length) { return; @@ -208,7 +208,7 @@ void SkRWBuffer::append(const void* src, size_t length) { fTotalUsed += length; if (nullptr == fHead) { - fHead = SkBufferHead::Alloc(length); + fHead = SkBufferHead::Alloc(length + reserve); fTail = &fHead->fBlock; } @@ -218,7 +218,7 @@ void SkRWBuffer::append(const void* src, size_t length) { length -= written; if (length) { - SkBufferBlock* block = SkBufferBlock::Alloc(length); + SkBufferBlock* block = SkBufferBlock::Alloc(length + reserve); fTail->fNext = block; fTail = block; written = fTail->append(src, length); -- cgit v1.2.3