From 93d5ffda58391fe819199bf5afddc622e067af7e Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Tue, 11 Feb 2014 15:07:26 +0000 Subject: [PATCH] Change growth function for SkWriter32 Add setCountExact to SkTDArray to allow external control of array growth. Use it to allow SkWriter to control the buffer growth pattern. Change buffer growth pattern to 1.5n+4096 BUG=skia:2125 R=tomhudson@google.com, mtklein@google.com, reed@google.com Author: iancottrell@google.com Review URL: https://codereview.chromium.org/150663014 git-svn-id: http://skia.googlecode.com/svn/trunk@13401 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/core/SkTDArray.h | 83 ++++++++++++++++++++++++++++++---------- src/core/SkWriter32.cpp | 12 +++--- 2 files changed, 68 insertions(+), 27 deletions(-) diff --git a/include/core/SkTDArray.h b/include/core/SkTDArray.h index 67254ccc9a..e51f2cd008 100644 --- a/include/core/SkTDArray.h +++ b/include/core/SkTDArray.h @@ -151,25 +151,43 @@ public: fCount = 0; } + /** + * Sets the number of elements in the array. + * If the array does not have space for count elements, it will increase + * the storage allocated to some amount greater than that required. + * It will never shrink the shrink the storage. + */ void setCount(int count) { + // TODO(mtklein): eliminate this method, setCountExact -> setCount + SkASSERT(count >= 0); if (count > fReserve) { - this->growBy(count - fCount); - } else { - fCount = count; + resizeStorageToAtLeast(count); } + fCount = count; + } + + /** + * Sets the number of elements in the array. + * If the array does not have space for count elements, it will increase + * the storage allocated to exactly the amount required, with no remaining + * reserved space. + * It will never shrink the shrink the storage. + */ + void setCountExact(int count) { + if (count > fReserve) { + this->resizeStorageToExact(count); + } + fCount = count; } void setReserve(int reserve) { if (reserve > fReserve) { - SkASSERT(reserve > fCount); - int count = fCount; - this->growBy(reserve - fCount); - fCount = count; + resizeStorageToAtLeast(reserve); } } T* prepend() { - this->growBy(1); + this->adjustCount(1); memmove(fArray + 1, fArray, (fCount - 1) * sizeof(T)); return fArray; } @@ -183,7 +201,7 @@ public: SkASSERT(src == NULL || fArray == NULL || src + count <= fArray || fArray + oldCount <= src); - this->growBy(count); + this->adjustCount(count); if (src) { memcpy(fArray + oldCount, src, sizeof(T) * count); } @@ -204,7 +222,7 @@ public: SkASSERT(count); SkASSERT(index <= fCount); size_t oldCount = fCount; - this->growBy(count); + this->adjustCount(count); T* dst = fArray + index; memmove(dst + count, dst, sizeof(T) * (oldCount - index)); if (src) { @@ -356,20 +374,43 @@ private: int fReserve; int fCount; - void growBy(int extra) { - SkASSERT(extra); - - if (fCount + extra > fReserve) { - int size = fCount + extra + 4; - size += size >> 2; + /** + * Adjusts the number of elements in the array. + * This is the same as calling setCount(count() + delta). + */ + void adjustCount(int delta) { + setCount(fCount + delta); + } - fArray = (T*)sk_realloc_throw(fArray, size * sizeof(T)); + /** + * This resizes the storage to *exactly* count elements, growing or + * shrinking the allocation as needed. It does not ASSERT anything about + * the previous allocation size, or about fCount. + * + * note: does NOT modify fCount + */ + void resizeStorageToExact(int count) { + SkASSERT(count >= 0); + fArray = (T*)sk_realloc_throw(fArray, count * sizeof(T)); #ifdef SK_DEBUG - fData = (ArrayT*)fArray; + fData = (ArrayT*)fArray; #endif - fReserve = size; - } - fCount += extra; + fReserve = count; + } + + /** + * Increase the storage allocation such that it can hold (fCount + extra) + * elements. + * It never shrinks the allocation, and it may increase the allocation by + * more than is strictly required, based on a private growth heuristic. + * + * note: does NOT modify fCount + */ + void resizeStorageToAtLeast(int count) { + SkASSERT(count > fReserve); + int space = count + 4; + space += space>>2; + resizeStorageToExact(space); } }; diff --git a/src/core/SkWriter32.cpp b/src/core/SkWriter32.cpp index 1e8a10c87c..76664e72b3 100644 --- a/src/core/SkWriter32.cpp +++ b/src/core/SkWriter32.cpp @@ -67,20 +67,20 @@ size_t SkWriter32::WriteStringSize(const char* str, size_t len) { return SkAlign4(lenBytes + len + 1); } +const size_t kMinBufferBytes=4096; + void SkWriter32::growToAtLeast(size_t size) { bool wasExternal = (fExternal != NULL) && (fData == fExternal); + fCapacity = kMinBufferBytes + + SkTMax(size, fCapacity + (fCapacity >> 1)); + // cause the buffer to grow - fInternal.setCount(size); + fInternal.setCountExact(fCapacity); fData = fInternal.begin(); if (wasExternal) { // we were external, so copy in the data memcpy(fData, fExternal, fUsed); } - // Find out the size the buffer grew to, it may be more than we asked for. - fCapacity = fInternal.reserved(); - // Expand the array so all reserved space is "used", we maintain the - // amount we have written manually outside the array - fInternal.setCount(fCapacity); SkASSERT(fInternal.count() == (int)fCapacity); SkASSERT(fInternal.reserved() == (int)fCapacity); } -- 2.34.1