Remove SkChunckAlloc
Change-Id: Ia400dd2d8aa398cf53852acd71c4a45228752496 Reviewed-on: https://skia-review.googlesource.com/9328 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
parent
7dd57b6a93
commit
3139de39d7
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "Benchmark.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkChunkAlloc.h"
|
||||
#include "SkPaint.h"
|
||||
#include "SkRandom.h"
|
||||
#include "SkString.h"
|
||||
|
||||
class ChunkAllocBench : public Benchmark {
|
||||
SkString fName;
|
||||
size_t fMinSize;
|
||||
public:
|
||||
ChunkAllocBench(size_t minSize) {
|
||||
fMinSize = minSize;
|
||||
fName.printf("chunkalloc_" SK_SIZE_T_SPECIFIER, minSize);
|
||||
}
|
||||
|
||||
bool isSuitableFor(Backend backend) override {
|
||||
return backend == kNonRendering_Backend;
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* onGetName() override {
|
||||
return fName.c_str();
|
||||
}
|
||||
|
||||
void onDraw(int loops, SkCanvas*) override {
|
||||
size_t inc = fMinSize >> 4;
|
||||
SkASSERT(inc > 0);
|
||||
size_t total = fMinSize * 64;
|
||||
|
||||
SkChunkAlloc alloc(fMinSize);
|
||||
|
||||
for (int i = 0; i < loops; ++i) {
|
||||
size_t size = 0;
|
||||
int calls = 0;
|
||||
while (size < total) {
|
||||
alloc.allocThrow(inc);
|
||||
size += inc;
|
||||
calls += 1;
|
||||
}
|
||||
alloc.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef Benchmark INHERITED;
|
||||
};
|
||||
|
||||
DEF_BENCH( return new ChunkAllocBench(64); )
|
||||
DEF_BENCH( return new ChunkAllocBench(8*1024); )
|
@ -71,7 +71,6 @@ bench_sources = [
|
||||
"$_bench/MatrixBench.cpp",
|
||||
"$_bench/MatrixConvolutionBench.cpp",
|
||||
"$_bench/MeasureBench.cpp",
|
||||
"$_bench/MemoryBench.cpp",
|
||||
"$_bench/MemsetBench.cpp",
|
||||
"$_bench/MergeBench.cpp",
|
||||
"$_bench/MipMapBench.cpp",
|
||||
|
@ -66,7 +66,6 @@ skia_core_sources = [
|
||||
"$_src/core/SkCachedData.cpp",
|
||||
"$_src/core/SkCanvas.cpp",
|
||||
"$_src/core/SkCanvasPriv.h",
|
||||
"$_src/core/SkChunkAlloc.cpp",
|
||||
"$_src/core/SkClipStack.cpp",
|
||||
"$_src/core/SkClipStack.h",
|
||||
"$_src/core/SkClipStackDevice.cpp",
|
||||
@ -452,7 +451,6 @@ skia_core_sources = [
|
||||
# private
|
||||
"$_include/private/SkAtomics.h",
|
||||
"$_include/private/SkChecksum.h",
|
||||
"$_include/private/SkChunkAlloc.h",
|
||||
"$_include/private/SkFixed.h",
|
||||
"$_include/private/SkFloatBits.h",
|
||||
"$_include/private/SkFloatingPoint.h",
|
||||
|
@ -1,89 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2006 The Android Open Source Project
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SkChunkAlloc_DEFINED
|
||||
#define SkChunkAlloc_DEFINED
|
||||
|
||||
#include "SkTypes.h"
|
||||
|
||||
class SkChunkAlloc : SkNoncopyable {
|
||||
public:
|
||||
SkChunkAlloc(size_t minSize);
|
||||
~SkChunkAlloc();
|
||||
|
||||
/**
|
||||
* Free up all allocated blocks. This invalidates all returned
|
||||
* pointers.
|
||||
*/
|
||||
void reset();
|
||||
/**
|
||||
* Reset to 0 used bytes preserving as much memory as possible.
|
||||
* This invalidates all returned pointers.
|
||||
*/
|
||||
void rewind();
|
||||
|
||||
enum AllocFailType {
|
||||
kReturnNil_AllocFailType,
|
||||
kThrow_AllocFailType
|
||||
};
|
||||
|
||||
/**
|
||||
* Allocates a memory block of size bytes.
|
||||
* On success: returns a pointer to beginning of memory block that is
|
||||
* 8 byte aligned. The content of allocated block is not initialized.
|
||||
* On failure: calls abort() if called with kThrow_AllocFailType,
|
||||
* otherwise returns NULL pointer.
|
||||
*/
|
||||
void* alloc(size_t bytes, AllocFailType);
|
||||
|
||||
/**
|
||||
* Shortcut for calling alloc with kThrow_AllocFailType.
|
||||
*/
|
||||
void* allocThrow(size_t bytes) {
|
||||
return this->alloc(bytes, kThrow_AllocFailType);
|
||||
}
|
||||
|
||||
/** Call this to unalloc the most-recently allocated ptr by alloc(). On
|
||||
success, the number of bytes freed is returned, or 0 if the block could
|
||||
not be unallocated. This is a hint to the underlying allocator that
|
||||
the previous allocation may be reused, but the implementation is free
|
||||
to ignore this call (and return 0).
|
||||
*/
|
||||
size_t unalloc(void* ptr);
|
||||
|
||||
size_t totalCapacity() const { return fTotalCapacity; }
|
||||
size_t totalUsed() const { return fTotalUsed; }
|
||||
SkDEBUGCODE(int blockCount() const { return fBlockCount; })
|
||||
SkDEBUGCODE(size_t totalLost() const { return fTotalLost; })
|
||||
|
||||
/**
|
||||
* Returns true if the specified address is within one of the chunks, and
|
||||
* has at least 1-byte following the address (i.e. if addr points to the
|
||||
* end of a chunk, then contains() will return false).
|
||||
*/
|
||||
bool contains(const void* addr) const;
|
||||
|
||||
private:
|
||||
struct Block;
|
||||
|
||||
Block* fBlock;
|
||||
size_t fMinSize;
|
||||
size_t fChunkSize;
|
||||
size_t fTotalCapacity;
|
||||
size_t fTotalUsed; // will be <= fTotalCapacity
|
||||
SkDEBUGCODE(int fBlockCount;)
|
||||
SkDEBUGCODE(size_t fTotalLost;) // will be <= fTotalCapacity
|
||||
|
||||
Block* newBlock(size_t bytes, AllocFailType ftype);
|
||||
Block* addBlockIfNecessary(size_t bytes, AllocFailType ftype);
|
||||
|
||||
SkDEBUGCODE(void validate();)
|
||||
};
|
||||
|
||||
#endif
|
@ -1,235 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006 The Android Open Source Project
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkChunkAlloc.h"
|
||||
|
||||
// Don't malloc any chunks smaller than this
|
||||
#define MIN_CHUNKALLOC_BLOCK_SIZE 1024
|
||||
|
||||
// Return the new min blocksize given the current value
|
||||
static size_t increase_next_size(size_t size) {
|
||||
return size + (size >> 1);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct SkChunkAlloc::Block {
|
||||
Block* fNext;
|
||||
size_t fFreeSize;
|
||||
char* fFreePtr;
|
||||
// data[] follows
|
||||
|
||||
size_t blockSize() const {
|
||||
char* start = this->startOfData();
|
||||
size_t bytes = fFreePtr - start;
|
||||
return fFreeSize + bytes;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
fNext = nullptr;
|
||||
fFreeSize = this->blockSize();
|
||||
fFreePtr = this->startOfData();
|
||||
}
|
||||
|
||||
char* startOfData() const {
|
||||
return reinterpret_cast<char*>(SkAlign8(reinterpret_cast<size_t>(this + 1)));
|
||||
}
|
||||
|
||||
static void FreeChain(Block* block) {
|
||||
while (block) {
|
||||
Block* next = block->fNext;
|
||||
sk_free(block);
|
||||
block = next;
|
||||
}
|
||||
}
|
||||
|
||||
bool contains(const void* addr) const {
|
||||
const char* ptr = reinterpret_cast<const char*>(addr);
|
||||
return ptr >= this->startOfData() && ptr < fFreePtr;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkChunkAlloc::SkChunkAlloc(size_t minSize) {
|
||||
if (minSize < MIN_CHUNKALLOC_BLOCK_SIZE) {
|
||||
minSize = MIN_CHUNKALLOC_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
fBlock = nullptr;
|
||||
fMinSize = minSize;
|
||||
fChunkSize = fMinSize;
|
||||
fTotalCapacity = 0;
|
||||
fTotalUsed = 0;
|
||||
SkDEBUGCODE(fTotalLost = 0;)
|
||||
SkDEBUGCODE(fBlockCount = 0;)
|
||||
}
|
||||
|
||||
SkChunkAlloc::~SkChunkAlloc() {
|
||||
this->reset();
|
||||
}
|
||||
|
||||
void SkChunkAlloc::reset() {
|
||||
Block::FreeChain(fBlock);
|
||||
fBlock = nullptr;
|
||||
fChunkSize = fMinSize; // reset to our initial minSize
|
||||
fTotalCapacity = 0;
|
||||
fTotalUsed = 0;
|
||||
SkDEBUGCODE(fTotalLost = 0;)
|
||||
SkDEBUGCODE(fBlockCount = 0;)
|
||||
}
|
||||
|
||||
void SkChunkAlloc::rewind() {
|
||||
SkDEBUGCODE(this->validate();)
|
||||
|
||||
Block* largest = fBlock;
|
||||
|
||||
if (largest) {
|
||||
Block* next;
|
||||
for (Block* cur = largest->fNext; cur; cur = next) {
|
||||
next = cur->fNext;
|
||||
if (cur->blockSize() > largest->blockSize()) {
|
||||
sk_free(largest);
|
||||
largest = cur;
|
||||
} else {
|
||||
sk_free(cur);
|
||||
}
|
||||
}
|
||||
|
||||
largest->reset();
|
||||
fTotalCapacity = largest->blockSize();
|
||||
SkDEBUGCODE(fBlockCount = 1;)
|
||||
} else {
|
||||
fTotalCapacity = 0;
|
||||
SkDEBUGCODE(fBlockCount = 0;)
|
||||
}
|
||||
|
||||
fBlock = largest;
|
||||
fChunkSize = fMinSize; // reset to our initial minSize
|
||||
fTotalUsed = 0;
|
||||
SkDEBUGCODE(fTotalLost = 0;)
|
||||
SkDEBUGCODE(this->validate();)
|
||||
}
|
||||
|
||||
SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
|
||||
size_t size = bytes;
|
||||
if (size < fChunkSize) {
|
||||
size = fChunkSize;
|
||||
}
|
||||
|
||||
Block* block = (Block*)sk_malloc_flags(SkAlign8(sizeof(Block)) + size,
|
||||
ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0);
|
||||
|
||||
if (block) {
|
||||
block->fFreeSize = size;
|
||||
block->fFreePtr = block->startOfData();
|
||||
|
||||
fTotalCapacity += size;
|
||||
SkDEBUGCODE(fBlockCount += 1;)
|
||||
|
||||
fChunkSize = increase_next_size(fChunkSize);
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
SkChunkAlloc::Block* SkChunkAlloc::addBlockIfNecessary(size_t bytes, AllocFailType ftype) {
|
||||
SkASSERT(SkIsAlign8(bytes));
|
||||
|
||||
if (!fBlock || bytes > fBlock->fFreeSize) {
|
||||
Block* block = this->newBlock(bytes, ftype);
|
||||
if (!block) {
|
||||
return nullptr;
|
||||
}
|
||||
#ifdef SK_DEBUG
|
||||
if (fBlock) {
|
||||
fTotalLost += fBlock->fFreeSize;
|
||||
}
|
||||
#endif
|
||||
block->fNext = fBlock;
|
||||
fBlock = block;
|
||||
}
|
||||
|
||||
SkASSERT(fBlock && bytes <= fBlock->fFreeSize);
|
||||
return fBlock;
|
||||
}
|
||||
|
||||
void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) {
|
||||
SkDEBUGCODE(this->validate();)
|
||||
|
||||
bytes = SkAlign8(bytes);
|
||||
|
||||
Block* block = this->addBlockIfNecessary(bytes, ftype);
|
||||
if (!block) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char* ptr = block->fFreePtr;
|
||||
|
||||
fTotalUsed += bytes;
|
||||
block->fFreeSize -= bytes;
|
||||
block->fFreePtr = ptr + bytes;
|
||||
SkDEBUGCODE(this->validate();)
|
||||
SkASSERT(SkIsAlign8((size_t)ptr));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
size_t SkChunkAlloc::unalloc(void* ptr) {
|
||||
SkDEBUGCODE(this->validate();)
|
||||
|
||||
size_t bytes = 0;
|
||||
Block* block = fBlock;
|
||||
if (block) {
|
||||
char* cPtr = reinterpret_cast<char*>(ptr);
|
||||
char* start = block->startOfData();
|
||||
if (start <= cPtr && cPtr < block->fFreePtr) {
|
||||
bytes = block->fFreePtr - cPtr;
|
||||
fTotalUsed -= bytes;
|
||||
block->fFreeSize += bytes;
|
||||
block->fFreePtr = cPtr;
|
||||
}
|
||||
}
|
||||
SkDEBUGCODE(this->validate();)
|
||||
return bytes;
|
||||
}
|
||||
|
||||
bool SkChunkAlloc::contains(const void* addr) const {
|
||||
const Block* block = fBlock;
|
||||
while (block) {
|
||||
if (block->contains(addr)) {
|
||||
return true;
|
||||
}
|
||||
block = block->fNext;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void SkChunkAlloc::validate() {
|
||||
int numBlocks = 0;
|
||||
size_t totCapacity = 0;
|
||||
size_t totUsed = 0;
|
||||
size_t totLost = 0;
|
||||
size_t totAvailable = 0;
|
||||
|
||||
for (Block* temp = fBlock; temp; temp = temp->fNext) {
|
||||
++numBlocks;
|
||||
totCapacity += temp->blockSize();
|
||||
totUsed += temp->fFreePtr - temp->startOfData();
|
||||
if (temp == fBlock) {
|
||||
totAvailable += temp->fFreeSize;
|
||||
} else {
|
||||
totLost += temp->fFreeSize;
|
||||
}
|
||||
}
|
||||
|
||||
SkASSERT(fBlockCount == numBlocks);
|
||||
SkASSERT(fTotalCapacity == totCapacity);
|
||||
SkASSERT(fTotalUsed == totUsed);
|
||||
SkASSERT(fTotalLost == totLost);
|
||||
SkASSERT(totCapacity == totUsed + totLost + totAvailable);
|
||||
}
|
||||
#endif
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "SkArenaAlloc.h"
|
||||
#include "SkBitmap.h"
|
||||
#include "SkChunkAlloc.h"
|
||||
#include "SkDescriptor.h"
|
||||
#include "SkGlyph.h"
|
||||
#include "SkPaint.h"
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "SkCanvas.h"
|
||||
#include "SkChecksum.h"
|
||||
#include "SkChunkAlloc.h"
|
||||
#include "SkReadBuffer.h"
|
||||
#include "SkWriteBuffer.h"
|
||||
#include "SkPaint.h"
|
||||
|
@ -5,98 +5,10 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkChunkAlloc.h"
|
||||
#include "SkRandom.h"
|
||||
#include "SkUtils.h"
|
||||
#include "Test.h"
|
||||
|
||||
static void check_alloc(skiatest::Reporter* reporter, const SkChunkAlloc& alloc,
|
||||
size_t capacity, size_t used, int numBlocks) {
|
||||
REPORTER_ASSERT(reporter, alloc.totalCapacity() >= capacity);
|
||||
REPORTER_ASSERT(reporter, alloc.totalUsed() == used);
|
||||
SkDEBUGCODE(REPORTER_ASSERT(reporter, alloc.blockCount() == numBlocks);)
|
||||
}
|
||||
|
||||
static void* simple_alloc(skiatest::Reporter* reporter, SkChunkAlloc* alloc, size_t size) {
|
||||
void* ptr = alloc->allocThrow(size);
|
||||
check_alloc(reporter, *alloc, size, size, 1);
|
||||
REPORTER_ASSERT(reporter, alloc->contains(ptr));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void check_alloc_alignment(skiatest::Reporter* reporter,
|
||||
SkChunkAlloc* alloc, size_t size) {
|
||||
const size_t kAlignment = 8;
|
||||
void* ptr = alloc->allocThrow(size);
|
||||
REPORTER_ASSERT(reporter, ptr != nullptr);
|
||||
REPORTER_ASSERT(reporter, (size_t)ptr % kAlignment == 0);
|
||||
}
|
||||
|
||||
static void test_chunkalloc(skiatest::Reporter* reporter) {
|
||||
static const size_t kMin = 1024;
|
||||
SkChunkAlloc alloc(kMin);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// check empty
|
||||
check_alloc(reporter, alloc, 0, 0, 0);
|
||||
REPORTER_ASSERT(reporter, !alloc.contains(nullptr));
|
||||
REPORTER_ASSERT(reporter, !alloc.contains(reporter));
|
||||
|
||||
// reset on empty allocator
|
||||
alloc.reset();
|
||||
check_alloc(reporter, alloc, 0, 0, 0);
|
||||
|
||||
// rewind on empty allocator
|
||||
alloc.rewind();
|
||||
check_alloc(reporter, alloc, 0, 0, 0);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// test reset when something is allocated
|
||||
size_t size = kMin >> 1;
|
||||
void* ptr = simple_alloc(reporter, &alloc, size);
|
||||
|
||||
alloc.reset();
|
||||
check_alloc(reporter, alloc, 0, 0, 0);
|
||||
REPORTER_ASSERT(reporter, !alloc.contains(ptr));
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// test rewind when something is allocated
|
||||
ptr = simple_alloc(reporter, &alloc, size);
|
||||
|
||||
alloc.rewind();
|
||||
check_alloc(reporter, alloc, size, 0, 1);
|
||||
REPORTER_ASSERT(reporter, !alloc.contains(ptr));
|
||||
|
||||
// use the available block
|
||||
ptr = simple_alloc(reporter, &alloc, size);
|
||||
alloc.reset();
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// test out allocating a second block
|
||||
ptr = simple_alloc(reporter, &alloc, size);
|
||||
|
||||
ptr = alloc.allocThrow(kMin);
|
||||
check_alloc(reporter, alloc, 2*kMin, size+kMin, 2);
|
||||
REPORTER_ASSERT(reporter, alloc.contains(ptr));
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// test out unalloc
|
||||
size_t freed = alloc.unalloc(ptr);
|
||||
REPORTER_ASSERT(reporter, freed == kMin);
|
||||
check_alloc(reporter, alloc, 2*kMin, size, 2);
|
||||
REPORTER_ASSERT(reporter, !alloc.contains(ptr));
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// test the alignment
|
||||
alloc.reset();
|
||||
SkRandom rand;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
check_alloc_alignment(reporter, &alloc, rand.nextU16());
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void set_zero(void* dst, size_t bytes) {
|
||||
char* ptr = (char*)dst;
|
||||
for (size_t i = 0; i < bytes; ++i) {
|
||||
@ -174,6 +86,4 @@ static void test_32(skiatest::Reporter* reporter) {
|
||||
DEF_TEST(Memset, reporter) {
|
||||
test_16(reporter);
|
||||
test_32(reporter);
|
||||
|
||||
test_chunkalloc(reporter);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user