diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2022-02-14 17:20:04 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-14 17:20:04 +0100 |
commit | 6e231823aa201df4ef82158d969864974727777b (patch) | |
tree | 5c3b253cba5e4a31088a9e7600be9507b3c1869f | |
parent | 8a20814df703deaf217b1cbc1611a5dcd9991fcb (diff) | |
parent | 377d6f802757cdc41a0c1db1de8bde0c81e9cd0d (diff) |
Merge pull request #21166 from vespa-engine/balder/balder/split-out-freelist-to-separate-file
Move FreeListT out to separate file.
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/CMakeLists.txt | 4 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/datasegment.cpp | 6 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/datasegment.h | 86 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/datasegment.hpp | 155 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/datasegmentd.cpp | 6 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/datasegmentdst.cpp | 6 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/freelist.cpp | 8 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/freelist.h | 91 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/freelist.hpp | 152 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/globalpool.h | 23 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/globalpool.hpp | 4 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/malloc.h | 19 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/threadpool.h | 11 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/threadpool.hpp | 2 |
14 files changed, 304 insertions, 269 deletions
diff --git a/vespamalloc/src/vespamalloc/malloc/CMakeLists.txt b/vespamalloc/src/vespamalloc/malloc/CMakeLists.txt index acac1aa5b85..c3a49161f32 100644 --- a/vespamalloc/src/vespamalloc/malloc/CMakeLists.txt +++ b/vespamalloc/src/vespamalloc/malloc/CMakeLists.txt @@ -4,6 +4,7 @@ vespa_add_library(vespamalloc_malloc OBJECT malloc.cpp allocchunk.cpp common.cpp + freelist.cpp mmappool.cpp threadproxy.cpp memblock.cpp @@ -18,6 +19,7 @@ vespa_add_library(vespamalloc_mallocd OBJECT mallocd.cpp allocchunk.cpp common.cpp + freelist.cpp mmappool.cpp threadproxy.cpp memblockboundscheck.cpp @@ -33,6 +35,7 @@ vespa_add_library(vespamalloc_mallocdst16 OBJECT mallocdst16.cpp allocchunk.cpp common.cpp + freelist.cpp mmappool.cpp threadproxy.cpp memblockboundscheck.cpp @@ -49,6 +52,7 @@ vespa_add_library(vespamalloc_mallocdst16_nl OBJECT mallocdst16_nl.cpp allocchunk.cpp common.cpp + freelist.cpp mmappool.cpp threadproxy.cpp memblockboundscheck.cpp diff --git a/vespamalloc/src/vespamalloc/malloc/datasegment.cpp b/vespamalloc/src/vespamalloc/malloc/datasegment.cpp index a8ff04793e7..d794fb88419 100644 --- a/vespamalloc/src/vespamalloc/malloc/datasegment.cpp +++ b/vespamalloc/src/vespamalloc/malloc/datasegment.cpp @@ -1,8 +1,8 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespamalloc/malloc/datasegment.hpp> -#include <vespamalloc/malloc/memblock.h> +#include "datasegment.hpp" +#include "memblock.h" -namespace vespamalloc { +namespace vespamalloc::segment { template class DataSegment<MemBlock>; diff --git a/vespamalloc/src/vespamalloc/malloc/datasegment.h b/vespamalloc/src/vespamalloc/malloc/datasegment.h index cefa961852f..ada9b46a241 100644 --- a/vespamalloc/src/vespamalloc/malloc/datasegment.h +++ b/vespamalloc/src/vespamalloc/malloc/datasegment.h @@ -1,20 +1,19 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #pragma once -#include <climits> -#include <memory> -#include <vespamalloc/malloc/common.h> +#include "common.h" +#include "freelist.h" #include <vespamalloc/util/traceutil.h> #include <vespamalloc/util/stream.h> -namespace vespamalloc { +namespace vespamalloc::segment { template<typename MemBlockPtrT> class DataSegment { public: - using BlockIdT = uint32_t; - enum { UNMAPPED_BLOCK=-4, UNUSED_BLOCK=-3, FREE_BLOCK=-2, SYSTEM_BLOCK=-1, NUM_ADMIN_CLASSES=4 }; + DataSegment(const DataSegment & rhs) = delete; + DataSegment & operator = (const DataSegment & rhs) = delete; DataSegment() __attribute__((noinline)); ~DataSegment() __attribute__((noinline)); @@ -22,7 +21,7 @@ public: void returnBlock(void *ptr) __attribute__((noinline)); SizeClassT sizeClass(const void * ptr) const { return _blockList[blockId(ptr)].sizeClass(); } bool containsPtr(const void * ptr) const { return blockId(ptr) < BlockCount; } - size_t getMaxSize(const void * ptr) const { return _blockList[blockId(ptr)].getMaxSize(); } + size_t getMaxSize(const void * ptr) const { return _blockList[blockId(ptr)].getMaxSize<MemBlockPtrT>(); } const void * start() const { return _osMemory.getStart(); } const void * end() const { return _osMemory.getEnd(); } static SizeClassT adjustedSizeClass(size_t sz) { return (sz >> 16) + 0x400; } @@ -42,79 +41,8 @@ public: checkAndLogBigSegment(); } void enableThreadSupport() { _mutex.init(); } - static BlockIdT blockId(const void * ptr) { - return (size_t(ptr) - Memory::getMinPreferredStartAddress())/BlockSize; - } - static void * fromBlockId(size_t id) { - return reinterpret_cast<void *>(id*BlockSize + Memory::getMinPreferredStartAddress()); - } -private: - const char * getAdminClassName(int id) { - switch (id) { - case UNMAPPED_BLOCK: return "UNMAPPED"; - case UNUSED_BLOCK: return "UNUSED"; - case FREE_BLOCK: return "FREE"; - case SYSTEM_BLOCK: return "SYSTEM"; - default: return "UNKNOWN"; - } - } - DataSegment(const DataSegment & rhs); - DataSegment & operator = (const DataSegment & rhs); - - // Allow for 1T heap - static constexpr size_t BlockSize = 0x200000ul; - static constexpr BlockIdT BlockCount = 0x80000; - class BlockT - { - public: - BlockT(SizeClassT szClass = UNUSED_BLOCK, BlockIdT numBlocks = 0) - : _sizeClass(szClass), _freeChainLength(0), _realNumBlocks(numBlocks) - { } - SizeClassT sizeClass() const { return _sizeClass; } - BlockIdT realNumBlocks() const { return _realNumBlocks; } - BlockIdT freeChainLength() const { return _freeChainLength; } - void sizeClass(SizeClassT sc) { _sizeClass = sc; } - void realNumBlocks(BlockIdT fc) { _realNumBlocks = fc; } - void freeChainLength(BlockIdT fc) { _freeChainLength = fc; } - size_t getMaxSize() const { - return MemBlockPtrT::unAdjustSize(std::min(MemBlockPtrT::classSize(_sizeClass), - size_t(_realNumBlocks) * BlockSize)); - } - private: - SizeClassT _sizeClass; - /// Number of blocks free from here and on. For memory reuse, big blocks only. - BlockIdT _freeChainLength; - /// Real number of blocks used. Used to avoid rounding for big blocks. - BlockIdT _realNumBlocks; - }; - - template <int MaxCount> - class FreeListT { - public: - using Index = BlockIdT; - FreeListT(BlockT * blockList) __attribute__((noinline)); - FreeListT(const FreeListT &) = delete; - FreeListT & operator =(const FreeListT &) = delete; - FreeListT(FreeListT &&) = delete; - FreeListT & operator =(FreeListT &&) = delete; - ~FreeListT(); - void add(Index startIndex) __attribute__((noinline)); - void * sub(Index numBlocks) __attribute__((noinline)); - Index lastBlock(Index nextBlock) __attribute__((noinline)); - void removeLastBlock() { - if (_count > 0) { - _count--; - } - } - Index numFreeBlocks() const; - void info(FILE * os) __attribute__((noinline)); - private: - void * linkOut(Index findex, Index left) __attribute__((noinline)); - BlockT *_blockList; - Index _count; - Index _freeStartIndex[MaxCount]; - }; +private: void checkAndLogBigSegment() __attribute__((noinline)); diff --git a/vespamalloc/src/vespamalloc/malloc/datasegment.hpp b/vespamalloc/src/vespamalloc/malloc/datasegment.hpp index 051773df21f..9c92bb19f7c 100644 --- a/vespamalloc/src/vespamalloc/malloc/datasegment.hpp +++ b/vespamalloc/src/vespamalloc/malloc/datasegment.hpp @@ -1,9 +1,9 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #pragma once -#include <vespamalloc/malloc/datasegment.h> +#include "datasegment.h" -namespace vespamalloc { +namespace vespamalloc::segment { template<typename MemBlockPtrT> DataSegment<MemBlockPtrT>::~DataSegment() = default; @@ -336,155 +336,4 @@ void DataSegment<MemBlockPtrT>::info(FILE * os, size_t level) } } -template<typename MemBlockPtrT> -template <int MaxCount> -DataSegment<MemBlockPtrT>::FreeListT<MaxCount>::FreeListT(BlockT * blockList) : - _blockList(blockList), - _count(0) -{ - for (size_t i = 0; i < NELEMS(_freeStartIndex); i++) { - _freeStartIndex[i] = -1; - } -} - -template<typename MemBlockPtrT> -template <int MaxCount> -DataSegment<MemBlockPtrT>::FreeListT<MaxCount>::~FreeListT() = default; - -template<typename MemBlockPtrT> -template <int MaxCount> -void -DataSegment<MemBlockPtrT>::FreeListT<MaxCount>::add(Index startIndex) -{ - Index i(0); - Index numBlocks(_blockList[startIndex].freeChainLength()); - for (i=0; (i < _count) && (_freeStartIndex[i] < startIndex); i++) { } - Index prevIndex(0), nextIndex(0); - BlockT * prev(nullptr), * next(nullptr); - if (i > 0) { - prevIndex = _freeStartIndex[i-1]; - prev = & _blockList[prevIndex]; - } - if (i < _count) { - nextIndex = _freeStartIndex[i]; - next = & _blockList[nextIndex]; - } - - if (prev && (prevIndex + prev->freeChainLength() == startIndex)) { - // Join with freeChain ahead. - prev->freeChainLength(prev->freeChainLength() + numBlocks); - startIndex = prevIndex; - } else if (next && (startIndex + numBlocks == nextIndex)) { - // Join with freeChain that follows. - _freeStartIndex[i] = startIndex; - nextIndex = startIndex; - Index oldNextCount = next->freeChainLength(); - next = & _blockList[startIndex]; - next->freeChainLength(oldNextCount + numBlocks); - } else { - // Insert. - for(Index j=0; j < (_count-i); j++) { - _freeStartIndex[_count-j] = _freeStartIndex[_count-j-1]; - } - _count++; - _freeStartIndex[i] = startIndex; - } - - if (prev && next && (prevIndex + prev->freeChainLength() == nextIndex)) { - prev->freeChainLength(prev->freeChainLength() + next->freeChainLength()); - _count--; - for(Index j=i; j < _count; j++) { - _freeStartIndex[j] = _freeStartIndex[j+1]; - } - _freeStartIndex[_count] = -1; - } -} - -template<typename MemBlockPtrT> -template <int MaxCount> -void * -DataSegment<MemBlockPtrT>::FreeListT<MaxCount>::sub(Index numBlocks) -{ - void * block(nullptr); - size_t bestFitIndex(_count); - int bestLeft(INT_MAX); - for(size_t i=0; i < _count; i++) { - size_t index(_freeStartIndex[i]); - BlockT & b = _blockList[index]; - int left = b.freeChainLength() - numBlocks; - if ((left >= 0) && (left < bestLeft)) { - bestLeft = left; - bestFitIndex = i; - } - } - if (bestLeft != INT_MAX) { - block = linkOut(bestFitIndex, bestLeft); - } - return block; -} - -template<typename MemBlockPtrT> -template <int MaxCount> -uint32_t -DataSegment<MemBlockPtrT>::FreeListT<MaxCount>::lastBlock(Index nextBlock) -{ - Index lastIndex(0); - if (_count > 0) { - Index index(_freeStartIndex[_count-1]); - BlockT & b = _blockList[index]; - if (index + b.freeChainLength() == nextBlock) { - lastIndex = index; - } - } - return lastIndex; -} - -template<typename MemBlockPtrT> -template <int MaxCount> -void -DataSegment<MemBlockPtrT>::FreeListT<MaxCount>::info(FILE * os) -{ - for (Index i=0; i < _count; i++) { - Index index(_freeStartIndex[i]); - const BlockT & b = _blockList[index]; - fprintf(os, "Free #%3d block #%5d chainlength %5d size %10lu\n", - i, index, b.freeChainLength(), b.freeChainLength()*BlockSize); - } -} - -template<typename MemBlockPtrT> -template <int MaxCount> -uint32_t -DataSegment<MemBlockPtrT>::FreeListT<MaxCount>::numFreeBlocks() const -{ - Index freeBlockCount(0); - for (Index i=0; i < _count; i++) { - Index index(_freeStartIndex[i]); - const BlockT & b = _blockList[index]; - freeBlockCount += b.freeChainLength(); - } - return freeBlockCount; -} - -template<typename MemBlockPtrT> -template <int MaxCount> -void * -DataSegment<MemBlockPtrT>::FreeListT<MaxCount>::linkOut(Index findex, Index left) -{ - size_t index(_freeStartIndex[findex]); - BlockT & b = _blockList[index]; - Index startIndex = index + left; - void *block = fromBlockId(startIndex); - if (left > 0) { - b.freeChainLength(left); - } else { - _count--; - for(Index j=findex; j < (_count); j++) { - _freeStartIndex[j] = _freeStartIndex[j+1]; - } - _freeStartIndex[_count] = -1; - } - return block; -} - } diff --git a/vespamalloc/src/vespamalloc/malloc/datasegmentd.cpp b/vespamalloc/src/vespamalloc/malloc/datasegmentd.cpp index c285f03fcf3..3842aae6297 100644 --- a/vespamalloc/src/vespamalloc/malloc/datasegmentd.cpp +++ b/vespamalloc/src/vespamalloc/malloc/datasegmentd.cpp @@ -1,8 +1,8 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespamalloc/malloc/datasegment.hpp> -#include <vespamalloc/malloc/memblockboundscheck_d.h> +#include "datasegment.hpp" +#include "memblockboundscheck_d.h" -namespace vespamalloc { +namespace vespamalloc::segment { template class DataSegment<MemBlockBoundsCheck>; diff --git a/vespamalloc/src/vespamalloc/malloc/datasegmentdst.cpp b/vespamalloc/src/vespamalloc/malloc/datasegmentdst.cpp index cb5b9c0981c..56504050a64 100644 --- a/vespamalloc/src/vespamalloc/malloc/datasegmentdst.cpp +++ b/vespamalloc/src/vespamalloc/malloc/datasegmentdst.cpp @@ -1,8 +1,8 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespamalloc/malloc/datasegment.hpp> -#include <vespamalloc/malloc/memblockboundscheck_dst.h> +#include "datasegment.hpp" +#include "memblockboundscheck_dst.h" -namespace vespamalloc { +namespace vespamalloc::segment { template class DataSegment<MemBlockBoundsCheck>; diff --git a/vespamalloc/src/vespamalloc/malloc/freelist.cpp b/vespamalloc/src/vespamalloc/malloc/freelist.cpp new file mode 100644 index 00000000000..8c9c4875207 --- /dev/null +++ b/vespamalloc/src/vespamalloc/malloc/freelist.cpp @@ -0,0 +1,8 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include "freelist.hpp" + +namespace vespamalloc::segment { + +template class FreeListT<0x40000>; + +} diff --git a/vespamalloc/src/vespamalloc/malloc/freelist.h b/vespamalloc/src/vespamalloc/malloc/freelist.h new file mode 100644 index 00000000000..977252b0a03 --- /dev/null +++ b/vespamalloc/src/vespamalloc/malloc/freelist.h @@ -0,0 +1,91 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#pragma once + +#include "common.h" + +namespace vespamalloc::segment { + +using BlockIdT = uint32_t; +enum { UNMAPPED_BLOCK=-4, UNUSED_BLOCK=-3, FREE_BLOCK=-2, SYSTEM_BLOCK=-1, NUM_ADMIN_CLASSES=4 }; + +inline +const char * +getAdminClassName(int id) { + switch (id) { + case UNMAPPED_BLOCK: return "UNMAPPED"; + case UNUSED_BLOCK: return "UNUSED"; + case FREE_BLOCK: return "FREE"; + case SYSTEM_BLOCK: return "SYSTEM"; + default: return "UNKNOWN"; + } +} + +// Allow for 1T heap +static constexpr size_t BlockSize = 0x200000ul; +static constexpr BlockIdT BlockCount = 0x80000; + +inline +BlockIdT +blockId(const void * ptr) { + return (size_t(ptr) - Memory::getMinPreferredStartAddress())/BlockSize; +} + +inline +void * +fromBlockId(size_t id) { + return reinterpret_cast<void *>(id*BlockSize + Memory::getMinPreferredStartAddress()); +} + +class BlockT +{ +public: + BlockT(SizeClassT szClass = UNUSED_BLOCK, BlockIdT numBlocks = 0) + : _sizeClass(szClass), _freeChainLength(0), _realNumBlocks(numBlocks) + { } + SizeClassT sizeClass() const { return _sizeClass; } + BlockIdT realNumBlocks() const { return _realNumBlocks; } + BlockIdT freeChainLength() const { return _freeChainLength; } + void sizeClass(SizeClassT sc) { _sizeClass = sc; } + void realNumBlocks(BlockIdT fc) { _realNumBlocks = fc; } + void freeChainLength(BlockIdT fc) { _freeChainLength = fc; } + template<typename MemBlockPtrT> + size_t getMaxSize() const { + return MemBlockPtrT::unAdjustSize(std::min(MemBlockPtrT::classSize(_sizeClass), + size_t(_realNumBlocks) * BlockSize)); + } +private: + SizeClassT _sizeClass; + /// Number of blocks free from here and on. For memory reuse, big blocks only. + BlockIdT _freeChainLength; + /// Real number of blocks used. Used to avoid rounding for big blocks. + BlockIdT _realNumBlocks; +}; + +template <int MaxCount> +class FreeListT { +public: + using Index = BlockIdT; + FreeListT(BlockT * blockList) __attribute__((noinline)); + FreeListT(const FreeListT &) = delete; + FreeListT & operator =(const FreeListT &) = delete; + FreeListT(FreeListT &&) = delete; + FreeListT & operator =(FreeListT &&) = delete; + ~FreeListT(); + void add(Index startIndex) __attribute__((noinline)); + void * sub(Index numBlocks) __attribute__((noinline)); + Index lastBlock(Index nextBlock) __attribute__((noinline)); + void removeLastBlock() { + if (_count > 0) { + _count--; + } + } + Index numFreeBlocks() const; + void info(FILE * os) __attribute__((noinline)); +private: + void * linkOut(Index findex, Index left) __attribute__((noinline)); + BlockT *_blockList; + Index _count; + Index _freeStartIndex[MaxCount]; +}; + +} diff --git a/vespamalloc/src/vespamalloc/malloc/freelist.hpp b/vespamalloc/src/vespamalloc/malloc/freelist.hpp new file mode 100644 index 00000000000..0bc812b8ad3 --- /dev/null +++ b/vespamalloc/src/vespamalloc/malloc/freelist.hpp @@ -0,0 +1,152 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#pragma once + +#include "freelist.h" + +namespace vespamalloc::segment { + + +template <int MaxCount> +FreeListT<MaxCount>::FreeListT(BlockT * blockList) : + _blockList(blockList), + _count(0) +{ + for (size_t i = 0; i < NELEMS(_freeStartIndex); i++) { + _freeStartIndex[i] = -1; + } +} + +template <int MaxCount> +FreeListT<MaxCount>::~FreeListT() = default; + +template <int MaxCount> +void +FreeListT<MaxCount>::add(Index startIndex) +{ + Index i(0); + Index numBlocks(_blockList[startIndex].freeChainLength()); + for (i=0; (i < _count) && (_freeStartIndex[i] < startIndex); i++) { } + Index prevIndex(0), nextIndex(0); + BlockT * prev(nullptr), * next(nullptr); + if (i > 0) { + prevIndex = _freeStartIndex[i-1]; + prev = & _blockList[prevIndex]; + } + if (i < _count) { + nextIndex = _freeStartIndex[i]; + next = & _blockList[nextIndex]; + } + + if (prev && (prevIndex + prev->freeChainLength() == startIndex)) { + // Join with freeChain ahead. + prev->freeChainLength(prev->freeChainLength() + numBlocks); + startIndex = prevIndex; + } else if (next && (startIndex + numBlocks == nextIndex)) { + // Join with freeChain that follows. + _freeStartIndex[i] = startIndex; + nextIndex = startIndex; + Index oldNextCount = next->freeChainLength(); + next = & _blockList[startIndex]; + next->freeChainLength(oldNextCount + numBlocks); + } else { + // Insert. + for(Index j=0; j < (_count-i); j++) { + _freeStartIndex[_count-j] = _freeStartIndex[_count-j-1]; + } + _count++; + _freeStartIndex[i] = startIndex; + } + + if (prev && next && (prevIndex + prev->freeChainLength() == nextIndex)) { + prev->freeChainLength(prev->freeChainLength() + next->freeChainLength()); + _count--; + for(Index j=i; j < _count; j++) { + _freeStartIndex[j] = _freeStartIndex[j+1]; + } + _freeStartIndex[_count] = -1; + } +} + +template <int MaxCount> +void * +FreeListT<MaxCount>::sub(Index numBlocks) +{ + void * block(nullptr); + size_t bestFitIndex(_count); + int bestLeft(INT_MAX); + for(size_t i=0; i < _count; i++) { + size_t index(_freeStartIndex[i]); + BlockT & b = _blockList[index]; + int left = b.freeChainLength() - numBlocks; + if ((left >= 0) && (left < bestLeft)) { + bestLeft = left; + bestFitIndex = i; + } + } + if (bestLeft != INT_MAX) { + block = linkOut(bestFitIndex, bestLeft); + } + return block; +} + +template <int MaxCount> +uint32_t +FreeListT<MaxCount>::lastBlock(Index nextBlock) +{ + Index lastIndex(0); + if (_count > 0) { + Index index(_freeStartIndex[_count-1]); + BlockT & b = _blockList[index]; + if (index + b.freeChainLength() == nextBlock) { + lastIndex = index; + } + } + return lastIndex; +} + +template <int MaxCount> +void +FreeListT<MaxCount>::info(FILE * os) +{ + for (Index i=0; i < _count; i++) { + Index index(_freeStartIndex[i]); + const BlockT & b = _blockList[index]; + fprintf(os, "Free #%3d block #%5d chainlength %5d size %10lu\n", + i, index, b.freeChainLength(), b.freeChainLength()*BlockSize); + } +} + +template <int MaxCount> +uint32_t +FreeListT<MaxCount>::numFreeBlocks() const +{ + Index freeBlockCount(0); + for (Index i=0; i < _count; i++) { + Index index(_freeStartIndex[i]); + const BlockT & b = _blockList[index]; + freeBlockCount += b.freeChainLength(); + } + return freeBlockCount; +} + +template <int MaxCount> +void * +FreeListT<MaxCount>::linkOut(Index findex, Index left) +{ + size_t index(_freeStartIndex[findex]); + BlockT & b = _blockList[index]; + Index startIndex = index + left; + void *block = fromBlockId(startIndex); + if (left > 0) { + b.freeChainLength(left); + } else { + _count--; + for(Index j=findex; j < (_count); j++) { + _freeStartIndex[j] = _freeStartIndex[j+1]; + } + _freeStartIndex[_count] = -1; + } + return block; +} + +} diff --git a/vespamalloc/src/vespamalloc/malloc/globalpool.h b/vespamalloc/src/vespamalloc/malloc/globalpool.h index a6b398bc1f1..ffe15921f3d 100644 --- a/vespamalloc/src/vespamalloc/malloc/globalpool.h +++ b/vespamalloc/src/vespamalloc/malloc/globalpool.h @@ -13,9 +13,10 @@ namespace vespamalloc { template <typename MemBlockPtrT> class AllocPoolT { + using DataSegment = segment::DataSegment<MemBlockPtrT>; public: typedef AFList<MemBlockPtrT> ChunkSList; - AllocPoolT(DataSegment<MemBlockPtrT> & ds); + AllocPoolT(DataSegment & ds); ~AllocPoolT(); ChunkSList *getFree(SizeClassT sc, size_t minBlocks); @@ -24,7 +25,7 @@ public: ChunkSList *exactAlloc(size_t exactSize, SizeClassT sc, ChunkSList * csl) __attribute__((noinline)); ChunkSList *returnMemory(SizeClassT sc, ChunkSList * csl) __attribute__((noinline)); - DataSegment<MemBlockPtrT> & dataSegment() { return _dataSegment; } + DataSegment & dataSegment() { return _dataSegment; } void enableThreadSupport() __attribute__((noinline)); static void setParams(size_t threadCacheLimit); @@ -71,15 +72,15 @@ private: } }; - Mutex _mutex; - ChunkSList * _chunkPool; - AllocFree _scList[NUM_SIZE_CLASSES]; - DataSegment<MemBlockPtrT> & _dataSegment; - std::atomic<size_t> _getChunks; - std::atomic<size_t> _getChunksSum; - std::atomic<size_t> _allocChunkList; - Stat _stat[NUM_SIZE_CLASSES]; - static size_t _threadCacheLimit __attribute__((visibility("hidden"))); + Mutex _mutex; + ChunkSList * _chunkPool; + AllocFree _scList[NUM_SIZE_CLASSES]; + DataSegment & _dataSegment; + std::atomic<size_t> _getChunks; + std::atomic<size_t> _getChunksSum; + std::atomic<size_t> _allocChunkList; + Stat _stat[NUM_SIZE_CLASSES]; + static size_t _threadCacheLimit __attribute__((visibility("hidden"))); }; } diff --git a/vespamalloc/src/vespamalloc/malloc/globalpool.hpp b/vespamalloc/src/vespamalloc/malloc/globalpool.hpp index ae9791f37b2..71694b9a653 100644 --- a/vespamalloc/src/vespamalloc/malloc/globalpool.hpp +++ b/vespamalloc/src/vespamalloc/malloc/globalpool.hpp @@ -11,7 +11,7 @@ template <typename MemBlockPtrT> size_t AllocPoolT<MemBlockPtrT>::_threadCacheLimit __attribute__((visibility("hidden"))) = 0x10000; template <typename MemBlockPtrT> -AllocPoolT<MemBlockPtrT>::AllocPoolT(DataSegment<MemBlockPtrT> & ds) +AllocPoolT<MemBlockPtrT>::AllocPoolT(DataSegment & ds) : _chunkPool(nullptr), _scList(), _dataSegment(ds), @@ -234,7 +234,7 @@ AllocPoolT<MemBlockPtrT>::allocChunkList(const Guard & guard) { (void) guard; size_t blockSize(sizeof(ChunkSList)*0x2000); - void * block = _dataSegment.getBlock(blockSize, _dataSegment.SYSTEM_BLOCK); + void * block = _dataSegment.getBlock(blockSize, segment::SYSTEM_BLOCK); ChunkSList * newList(nullptr); if (block != nullptr) { size_t chunksInBlock(blockSize/sizeof(ChunkSList)); diff --git a/vespamalloc/src/vespamalloc/malloc/malloc.h b/vespamalloc/src/vespamalloc/malloc/malloc.h index f35184cc581..ce9a6e71d78 100644 --- a/vespamalloc/src/vespamalloc/malloc/malloc.h +++ b/vespamalloc/src/vespamalloc/malloc/malloc.h @@ -14,6 +14,7 @@ namespace vespamalloc { template <typename MemBlockPtrT, typename ThreadListT> class MemoryManager : public IAllocator { + using DataSegment = segment::DataSegment<MemBlockPtrT>; public: MemoryManager(size_t logLimitAtStart); ~MemoryManager() override; @@ -76,18 +77,18 @@ public: _threadList.setParams(threadCacheLimit); _allocPool.setParams(threadCacheLimit); } - const DataSegment<MemBlockPtrT> & dataSegment() const { return _segment; } + const DataSegment & dataSegment() const { return _segment; } const MMapPool & mmapPool() const { return _mmapPool; } private: void freeSC(void *ptr, SizeClassT sc); - void crash() __attribute__((noinline));; - typedef AllocPoolT<MemBlockPtrT> AllocPool; - typedef typename ThreadListT::ThreadPool ThreadPool; - size_t _prAllocLimit; - DataSegment<MemBlockPtrT> _segment; - AllocPool _allocPool; - MMapPool _mmapPool; - ThreadListT _threadList; + void crash() __attribute__((noinline)); + using AllocPool = AllocPoolT<MemBlockPtrT>; + using ThreadPool = typename ThreadListT::ThreadPool; + size_t _prAllocLimit; + DataSegment _segment; + AllocPool _allocPool; + MMapPool _mmapPool; + ThreadListT _threadList; }; template <typename MemBlockPtrT, typename ThreadListT> diff --git a/vespamalloc/src/vespamalloc/malloc/threadpool.h b/vespamalloc/src/vespamalloc/malloc/threadpool.h index 1276d0129b5..0d7baa85781 100644 --- a/vespamalloc/src/vespamalloc/malloc/threadpool.h +++ b/vespamalloc/src/vespamalloc/malloc/threadpool.h @@ -1,11 +1,11 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #pragma once +#include "common.h" +#include "allocchunk.h" +#include "globalpool.h" +#include "mmappool.h" #include <atomic> -#include <vespamalloc/malloc/common.h> -#include <vespamalloc/malloc/allocchunk.h> -#include <vespamalloc/malloc/globalpool.h> -#include <vespamalloc/malloc/mmappool.h> namespace vespamalloc { @@ -15,6 +15,7 @@ class ThreadPoolT public: using ChunkSList = AFList<MemBlockPtrT>; using AllocPool = AllocPoolT<MemBlockPtrT>; + using DataSegment = segment::DataSegment<MemBlockPtrT>; ThreadPoolT(); ~ThreadPoolT(); void setPool(AllocPool & allocPool, MMapPool & mmapPool) { @@ -25,7 +26,7 @@ public: void malloc(size_t sz, MemBlockPtrT & mem); void free(MemBlockPtrT mem, SizeClassT sc); - void info(FILE * os, size_t level, const DataSegment<MemBlockPtrT> & ds) const __attribute__((noinline)); + void info(FILE * os, size_t level, const DataSegment & ds) const __attribute__((noinline)); /** * Indicates if it represents an active thread. * @return true if this represents an active thread. diff --git a/vespamalloc/src/vespamalloc/malloc/threadpool.hpp b/vespamalloc/src/vespamalloc/malloc/threadpool.hpp index 31ed1296a9e..7d177c4c129 100644 --- a/vespamalloc/src/vespamalloc/malloc/threadpool.hpp +++ b/vespamalloc/src/vespamalloc/malloc/threadpool.hpp @@ -16,7 +16,7 @@ size_t ThreadPoolT<MemBlockPtrT, ThreadStatT>::_threadCacheLimit __attribute__(( template <typename MemBlockPtrT, typename ThreadStatT> void -ThreadPoolT<MemBlockPtrT, ThreadStatT>::info(FILE * os, size_t level, const DataSegment<MemBlockPtrT> & ds) const { +ThreadPoolT<MemBlockPtrT, ThreadStatT>::info(FILE * os, size_t level, const DataSegment & ds) const { if (level > 0) { for (size_t i=0; i < NELEMS(_stat); i++) { const ThreadStatT & s = _stat[i]; |