+++ /dev/null
-/*
- * 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); )
"$_bench/MatrixBench.cpp",
"$_bench/MatrixConvolutionBench.cpp",
"$_bench/MeasureBench.cpp",
- "$_bench/MemoryBench.cpp",
"$_bench/MemsetBench.cpp",
"$_bench/MergeBench.cpp",
"$_bench/MipMapBench.cpp",
"$_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",
# 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",
+++ /dev/null
-
-/*
- * 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
+++ /dev/null
-/*
- * 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
#include "SkArenaAlloc.h"
#include "SkBitmap.h"
-#include "SkChunkAlloc.h"
#include "SkDescriptor.h"
#include "SkGlyph.h"
#include "SkPaint.h"
#include "SkCanvas.h"
#include "SkChecksum.h"
-#include "SkChunkAlloc.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
#include "SkPaint.h"
* 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) {
DEF_TEST(Memset, reporter) {
test_16(reporter);
test_32(reporter);
-
- test_chunkalloc(reporter);
}