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
This commit is contained in:
fmalita 2016-09-30 13:34:19 -07:00 committed by Commit bot
parent f6566314f8
commit 5776508126
2 changed files with 12 additions and 4 deletions

View File

@ -79,7 +79,15 @@ public:
~SkRWBuffer(); ~SkRWBuffer();
size_t size() const { return fTotalUsed; } 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; SkROBuffer* newRBufferSnapshot() const;
SkStreamAsset* newStreamSnapshot() const; SkStreamAsset* newStreamSnapshot() const;

View File

@ -199,7 +199,7 @@ SkRWBuffer::~SkRWBuffer() {
// next, since our reader will be using fCapacity (min'd against its total available) to know how // 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. // 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(); this->validate();
if (0 == length) { if (0 == length) {
return; return;
@ -208,7 +208,7 @@ void SkRWBuffer::append(const void* src, size_t length) {
fTotalUsed += length; fTotalUsed += length;
if (nullptr == fHead) { if (nullptr == fHead) {
fHead = SkBufferHead::Alloc(length); fHead = SkBufferHead::Alloc(length + reserve);
fTail = &fHead->fBlock; fTail = &fHead->fBlock;
} }
@ -218,7 +218,7 @@ void SkRWBuffer::append(const void* src, size_t length) {
length -= written; length -= written;
if (length) { if (length) {
SkBufferBlock* block = SkBufferBlock::Alloc(length); SkBufferBlock* block = SkBufferBlock::Alloc(length + reserve);
fTail->fNext = block; fTail->fNext = block;
fTail = block; fTail = block;
written = fTail->append(src, length); written = fTail->append(src, length);