summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2022-02-14 17:20:04 +0100
committerGitHub <noreply@github.com>2022-02-14 17:20:04 +0100
commit6e231823aa201df4ef82158d969864974727777b (patch)
tree5c3b253cba5e4a31088a9e7600be9507b3c1869f
parent8a20814df703deaf217b1cbc1611a5dcd9991fcb (diff)
parent377d6f802757cdc41a0c1db1de8bde0c81e9cd0d (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.txt4
-rw-r--r--vespamalloc/src/vespamalloc/malloc/datasegment.cpp6
-rw-r--r--vespamalloc/src/vespamalloc/malloc/datasegment.h86
-rw-r--r--vespamalloc/src/vespamalloc/malloc/datasegment.hpp155
-rw-r--r--vespamalloc/src/vespamalloc/malloc/datasegmentd.cpp6
-rw-r--r--vespamalloc/src/vespamalloc/malloc/datasegmentdst.cpp6
-rw-r--r--vespamalloc/src/vespamalloc/malloc/freelist.cpp8
-rw-r--r--vespamalloc/src/vespamalloc/malloc/freelist.h91
-rw-r--r--vespamalloc/src/vespamalloc/malloc/freelist.hpp152
-rw-r--r--vespamalloc/src/vespamalloc/malloc/globalpool.h23
-rw-r--r--vespamalloc/src/vespamalloc/malloc/globalpool.hpp4
-rw-r--r--vespamalloc/src/vespamalloc/malloc/malloc.h19
-rw-r--r--vespamalloc/src/vespamalloc/malloc/threadpool.h11
-rw-r--r--vespamalloc/src/vespamalloc/malloc/threadpool.hpp2
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];