combine glyph and image bulk alloc, and adjust initial alloc size, to reduce total waste from 50% to 30%
add diagnostics to measure cache efficiency BUG= Review URL: https://codereview.chromium.org/17449012 git-svn-id: http://skia.googlecode.com/svn/trunk@9691 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
3832da1e9c
commit
6757a3c71f
@ -42,6 +42,7 @@ public:
|
|||||||
size_t unalloc(void* ptr);
|
size_t unalloc(void* ptr);
|
||||||
|
|
||||||
size_t totalCapacity() const { return fTotalCapacity; }
|
size_t totalCapacity() const { return fTotalCapacity; }
|
||||||
|
size_t totalUsed() const { return fTotalUsed; }
|
||||||
int blockCount() const { return fBlockCount; }
|
int blockCount() const { return fBlockCount; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,6 +59,7 @@ private:
|
|||||||
size_t fMinSize;
|
size_t fMinSize;
|
||||||
size_t fChunkSize;
|
size_t fChunkSize;
|
||||||
size_t fTotalCapacity;
|
size_t fTotalCapacity;
|
||||||
|
size_t fTotalUsed; // will be <= fTotalCapacity
|
||||||
int fBlockCount;
|
int fBlockCount;
|
||||||
|
|
||||||
Block* newBlock(size_t bytes, AllocFailType ftype);
|
Block* newBlock(size_t bytes, AllocFailType ftype);
|
||||||
|
@ -52,6 +52,7 @@ SkChunkAlloc::SkChunkAlloc(size_t minSize) {
|
|||||||
fMinSize = minSize;
|
fMinSize = minSize;
|
||||||
fChunkSize = fMinSize;
|
fChunkSize = fMinSize;
|
||||||
fTotalCapacity = 0;
|
fTotalCapacity = 0;
|
||||||
|
fTotalUsed = 0;
|
||||||
fBlockCount = 0;
|
fBlockCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ void SkChunkAlloc::reset() {
|
|||||||
fBlock = NULL;
|
fBlock = NULL;
|
||||||
fChunkSize = fMinSize; // reset to our initial minSize
|
fChunkSize = fMinSize; // reset to our initial minSize
|
||||||
fTotalCapacity = 0;
|
fTotalCapacity = 0;
|
||||||
|
fTotalUsed = 0;
|
||||||
fBlockCount = 0;
|
fBlockCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +92,8 @@ SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) {
|
void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) {
|
||||||
|
fTotalUsed += bytes;
|
||||||
|
|
||||||
bytes = SkAlign4(bytes);
|
bytes = SkAlign4(bytes);
|
||||||
|
|
||||||
Block* block = fBlock;
|
Block* block = fBlock;
|
||||||
|
@ -48,14 +48,13 @@ bool gSkSuppressFontCachePurgeSpew;
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define kMinGlphAlloc (sizeof(SkGlyph) * 64)
|
// so we don't grow our arrays a lot
|
||||||
#define kMinImageAlloc (24 * 64) // should be pointsize-dependent
|
#define kMinGlyphCount 16
|
||||||
|
#define kMinGlyphImageSize (16*2)
|
||||||
#define METRICS_RESERVE_COUNT 128 // so we don't grow this array a lot
|
#define kMinAllocAmount ((sizeof(SkGlyph) + kMinGlyphImageSize) * kMinGlyphCount)
|
||||||
|
|
||||||
SkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc)
|
SkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc)
|
||||||
: fGlyphAlloc(kMinGlphAlloc)
|
: fGlyphAlloc(kMinAllocAmount) {
|
||||||
, fImageAlloc(kMinImageAlloc) {
|
|
||||||
SkASSERT(typeface);
|
SkASSERT(typeface);
|
||||||
|
|
||||||
fPrev = fNext = NULL;
|
fPrev = fNext = NULL;
|
||||||
@ -69,9 +68,9 @@ SkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc)
|
|||||||
// init with 0xFF so that the charCode field will be -1, which is invalid
|
// init with 0xFF so that the charCode field will be -1, which is invalid
|
||||||
memset(fCharToGlyphHash, 0xFF, sizeof(fCharToGlyphHash));
|
memset(fCharToGlyphHash, 0xFF, sizeof(fCharToGlyphHash));
|
||||||
|
|
||||||
fMemoryUsed = sizeof(*this) + kMinGlphAlloc + kMinImageAlloc;
|
fMemoryUsed = sizeof(*this);
|
||||||
|
|
||||||
fGlyphArray.setReserve(METRICS_RESERVE_COUNT);
|
fGlyphArray.setReserve(kMinGlyphCount);
|
||||||
|
|
||||||
fMetricsCount = 0;
|
fMetricsCount = 0;
|
||||||
fAdvanceCount = 0;
|
fAdvanceCount = 0;
|
||||||
@ -79,6 +78,30 @@ SkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SkGlyphCache::~SkGlyphCache() {
|
SkGlyphCache::~SkGlyphCache() {
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
size_t ptrMem = fGlyphArray.count() * sizeof(SkGlyph*);
|
||||||
|
size_t glyphAlloc = fGlyphAlloc.totalCapacity();
|
||||||
|
size_t glyphHashUsed = 0;
|
||||||
|
size_t uniHashUsed = 0;
|
||||||
|
for (int i = 0; i < kHashCount; ++i) {
|
||||||
|
glyphHashUsed += fGlyphHash[i] ? sizeof(fGlyphHash[0]) : 0;
|
||||||
|
uniHashUsed += fCharToGlyphHash[i].fID != 0xFFFFFFFF ? sizeof(fCharToGlyphHash[0]) : 0;
|
||||||
|
}
|
||||||
|
size_t glyphUsed = fGlyphArray.count() * sizeof(SkGlyph);
|
||||||
|
size_t imageUsed = 0;
|
||||||
|
for (int i = 0; i < fGlyphArray.count(); ++i) {
|
||||||
|
const SkGlyph& g = *fGlyphArray[i];
|
||||||
|
if (g.fImage) {
|
||||||
|
imageUsed += g.fHeight * g.rowBytes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("glyphPtrArray,%zu, Alloc,%zu, imageUsed,%zu, glyphUsed,%zu, glyphHashAlloc,%zu, glyphHashUsed,%zu, unicharHashAlloc,%zu, unicharHashUsed,%zu\n",
|
||||||
|
ptrMem, glyphAlloc, imageUsed, glyphUsed, sizeof(fGlyphHash), glyphHashUsed, sizeof(fCharToGlyphHash), uniHashUsed);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
SkGlyph** gptr = fGlyphArray.begin();
|
SkGlyph** gptr = fGlyphArray.begin();
|
||||||
SkGlyph** stop = fGlyphArray.end();
|
SkGlyph** stop = fGlyphArray.end();
|
||||||
while (gptr < stop) {
|
while (gptr < stop) {
|
||||||
@ -296,7 +319,7 @@ const void* SkGlyphCache::findImage(const SkGlyph& glyph) {
|
|||||||
if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) {
|
if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) {
|
||||||
if (glyph.fImage == NULL) {
|
if (glyph.fImage == NULL) {
|
||||||
size_t size = glyph.computeImageSize();
|
size_t size = glyph.computeImageSize();
|
||||||
const_cast<SkGlyph&>(glyph).fImage = fImageAlloc.alloc(size,
|
const_cast<SkGlyph&>(glyph).fImage = fGlyphAlloc.alloc(size,
|
||||||
SkChunkAlloc::kReturnNil_AllocFailType);
|
SkChunkAlloc::kReturnNil_AllocFailType);
|
||||||
// check that alloc() actually succeeded
|
// check that alloc() actually succeeded
|
||||||
if (glyph.fImage) {
|
if (glyph.fImage) {
|
||||||
@ -708,7 +731,7 @@ void SkGlyphCache::validate() const {
|
|||||||
SkASSERT(glyph);
|
SkASSERT(glyph);
|
||||||
SkASSERT(fGlyphAlloc.contains(glyph));
|
SkASSERT(fGlyphAlloc.contains(glyph));
|
||||||
if (glyph->fImage) {
|
if (glyph->fImage) {
|
||||||
SkASSERT(fImageAlloc.contains(glyph->fImage));
|
SkASSERT(fGlyphAlloc.contains(glyph->fImage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -230,7 +230,6 @@ private:
|
|||||||
SkGlyph* fGlyphHash[kHashCount];
|
SkGlyph* fGlyphHash[kHashCount];
|
||||||
SkTDArray<SkGlyph*> fGlyphArray;
|
SkTDArray<SkGlyph*> fGlyphArray;
|
||||||
SkChunkAlloc fGlyphAlloc;
|
SkChunkAlloc fGlyphAlloc;
|
||||||
SkChunkAlloc fImageAlloc;
|
|
||||||
|
|
||||||
int fMetricsCount, fAdvanceCount;
|
int fMetricsCount, fAdvanceCount;
|
||||||
|
|
||||||
|
@ -14,22 +14,27 @@ static void test_chunkalloc(skiatest::Reporter* reporter) {
|
|||||||
SkChunkAlloc alloc(min);
|
SkChunkAlloc alloc(min);
|
||||||
|
|
||||||
REPORTER_ASSERT(reporter, 0 == alloc.totalCapacity());
|
REPORTER_ASSERT(reporter, 0 == alloc.totalCapacity());
|
||||||
|
REPORTER_ASSERT(reporter, 0 == alloc.totalUsed());
|
||||||
REPORTER_ASSERT(reporter, 0 == alloc.blockCount());
|
REPORTER_ASSERT(reporter, 0 == alloc.blockCount());
|
||||||
REPORTER_ASSERT(reporter, !alloc.contains(NULL));
|
REPORTER_ASSERT(reporter, !alloc.contains(NULL));
|
||||||
REPORTER_ASSERT(reporter, !alloc.contains(reporter));
|
REPORTER_ASSERT(reporter, !alloc.contains(reporter));
|
||||||
|
|
||||||
alloc.reset();
|
alloc.reset();
|
||||||
REPORTER_ASSERT(reporter, 0 == alloc.totalCapacity());
|
REPORTER_ASSERT(reporter, 0 == alloc.totalCapacity());
|
||||||
|
REPORTER_ASSERT(reporter, 0 == alloc.totalUsed());
|
||||||
REPORTER_ASSERT(reporter, 0 == alloc.blockCount());
|
REPORTER_ASSERT(reporter, 0 == alloc.blockCount());
|
||||||
|
|
||||||
size_t size = min >> 1;
|
size_t size = min >> 1;
|
||||||
void* ptr = alloc.allocThrow(size);
|
void* ptr = alloc.allocThrow(size);
|
||||||
REPORTER_ASSERT(reporter, alloc.totalCapacity() >= size);
|
REPORTER_ASSERT(reporter, alloc.totalCapacity() >= size);
|
||||||
|
REPORTER_ASSERT(reporter, alloc.totalUsed() == size);
|
||||||
REPORTER_ASSERT(reporter, alloc.blockCount() > 0);
|
REPORTER_ASSERT(reporter, alloc.blockCount() > 0);
|
||||||
REPORTER_ASSERT(reporter, alloc.contains(ptr));
|
REPORTER_ASSERT(reporter, alloc.contains(ptr));
|
||||||
|
|
||||||
alloc.reset();
|
alloc.reset();
|
||||||
REPORTER_ASSERT(reporter, !alloc.contains(ptr));
|
REPORTER_ASSERT(reporter, !alloc.contains(ptr));
|
||||||
|
REPORTER_ASSERT(reporter, 0 == alloc.totalCapacity());
|
||||||
|
REPORTER_ASSERT(reporter, 0 == alloc.totalUsed());
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
Reference in New Issue
Block a user