aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib
diff options
context:
space:
mode:
authorGeir Storli <geirstorli@yahoo.no>2016-11-23 09:43:57 +0100
committerGitHub <noreply@github.com>2016-11-23 09:43:57 +0100
commitaae2ec4d391352dc7d9db692f6377f00ca26f99e (patch)
treebb6ec810f3df9ab2a9203241c7e06b73fb70813d /searchlib
parent7910e750249203f69df10838499ae0263e813f20 (diff)
parent24b30fcbca1afdfa2abc5ba0e4368b7fcf58c734 (diff)
Merge pull request #1161 from yahoo/toregge/tweak-buffer-type-allocations
Toregge/tweak buffer type allocations
Diffstat (limited to 'searchlib')
-rw-r--r--searchlib/src/tests/attribute/multi_value_mapping2/multi_value_mapping2_test.cpp10
-rw-r--r--searchlib/src/tests/datastore/datastore/datastore_test.cpp61
-rw-r--r--searchlib/src/vespa/searchlib/attribute/enumstorebase.cpp8
-rw-r--r--searchlib/src/vespa/searchlib/attribute/enumstorebase.h2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multi_value_mapping2.h2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multi_value_mapping2.hpp4
-rw-r--r--searchlib/src/vespa/searchlib/datastore/array_store.h4
-rw-r--r--searchlib/src/vespa/searchlib/datastore/array_store.hpp12
-rw-r--r--searchlib/src/vespa/searchlib/datastore/buffer_type.cpp43
-rw-r--r--searchlib/src/vespa/searchlib/datastore/buffer_type.h15
-rw-r--r--searchlib/src/vespa/searchlib/datastore/bufferstate.cpp5
-rw-r--r--searchlib/src/vespa/searchlib/datastore/bufferstate.h6
-rw-r--r--searchlib/src/vespa/searchlib/datastore/datastorebase.cpp39
-rw-r--r--searchlib/src/vespa/searchlib/datastore/datastorebase.h10
14 files changed, 154 insertions, 67 deletions
diff --git a/searchlib/src/tests/attribute/multi_value_mapping2/multi_value_mapping2_test.cpp b/searchlib/src/tests/attribute/multi_value_mapping2/multi_value_mapping2_test.cpp
index 54a643e689a..474f361d9c4 100644
--- a/searchlib/src/tests/attribute/multi_value_mapping2/multi_value_mapping2_test.cpp
+++ b/searchlib/src/tests/attribute/multi_value_mapping2/multi_value_mapping2_test.cpp
@@ -73,8 +73,8 @@ public:
_attr(_mvMapping)
{
}
- Fixture(uint32_t maxSmallArraySize, size_t minClusters, size_t maxClusters)
- : _mvMapping(maxSmallArraySize, minClusters, maxClusters),
+ Fixture(uint32_t maxSmallArraySize, size_t minClusters, size_t maxClusters, size_t numClustersForNewBuffer)
+ : _mvMapping(maxSmallArraySize, minClusters, maxClusters, numClustersForNewBuffer),
_attr(_mvMapping)
{
}
@@ -146,8 +146,8 @@ public:
_rnd.srand48(32);
}
- IntFixture(uint32_t maxSmallArraySize, size_t minClusters, size_t maxClusters)
- : Fixture<int>(maxSmallArraySize, minClusters, maxClusters),
+ IntFixture(uint32_t maxSmallArraySize, size_t minClusters, size_t maxClusters, size_t numClustersForNewBuffer)
+ : Fixture<int>(maxSmallArraySize, minClusters, maxClusters, numClustersForNewBuffer),
_rnd(),
_refMapping(),
_maxSmallArraySize(maxSmallArraySize)
@@ -295,7 +295,7 @@ TEST_F("Test that replace works", Fixture<int>(3))
EXPECT_EQUAL(4u, f.getTotalValueCnt());
}
-TEST_F("Test that compaction works", IntFixture(3, 64, 512))
+TEST_F("Test that compaction works", IntFixture(3, 64, 512, 129))
{
uint32_t addDocs = 10;
uint32_t bufferCountBefore = 0;
diff --git a/searchlib/src/tests/datastore/datastore/datastore_test.cpp b/searchlib/src/tests/datastore/datastore/datastore_test.cpp
index de673c8c0c9..5cfd88cc1da 100644
--- a/searchlib/src/tests/datastore/datastore/datastore_test.cpp
+++ b/searchlib/src/tests/datastore/datastore/datastore_test.cpp
@@ -5,6 +5,7 @@ LOG_SETUP("datastore_test");
#include <vespa/vespalib/testkit/testapp.h>
#include <vespa/searchlib/datastore/datastore.h>
#include <vespa/searchlib/datastore/datastore.hpp>
+#include <vespa/vespalib/test/insertion_operators.h>
namespace search {
namespace datastore {
@@ -59,6 +60,47 @@ public:
size_t activeBufferId() const { return _activeBufferIds[0]; }
};
+
+using GrowthStats = std::vector<int>;
+
+class GrowStore
+{
+ using Store = DataStoreT<EntryRefT<22>>;
+ using RefType = Store::RefType;
+ Store _store;
+ BufferType<int> _type;
+ uint32_t _typeId;
+public:
+ GrowStore(size_t minSwitch)
+ : _store(),
+ _type(1, 4, 64, minSwitch),
+ _typeId(0)
+ {
+ _typeId = _store.addType(&_type);
+ _store.initActiveBuffers();
+ }
+ GrowStore() : GrowStore(0) { }
+ ~GrowStore() { _store.dropBuffers(); }
+
+ GrowthStats getGrowthStats(size_t bufs) {
+ GrowthStats sizes;
+ int i = 0;
+ int prevBuffer = -1;
+ while (sizes.size() < bufs) {
+ RefType iRef = _store.allocNewEntry<int>(_typeId).first;
+ int buffer = iRef.bufferId();
+ if (buffer != prevBuffer) {
+ if (prevBuffer >= 0) {
+ sizes.push_back(i);
+ }
+ prevBuffer = buffer;
+ }
+ ++i;
+ }
+ return sizes;
+ }
+};
+
typedef MyStore::RefType MyRef;
class Test : public vespalib::TestApp {
@@ -74,9 +116,8 @@ private:
void requireThatWeCanUseFreeLists();
void requireThatMemoryStatsAreCalculated();
void requireThatMemoryUsageIsCalculated();
-
- void
- requireThatWecanDisableElemHoldList(void);
+ void requireThatWecanDisableElemHoldList(void);
+ void requireThatBufferGrowthWorks();
public:
int Main();
};
@@ -406,6 +447,19 @@ Test::requireThatWecanDisableElemHoldList(void)
s.trimHoldLists(101);
}
+void
+Test::requireThatBufferGrowthWorks()
+{
+ // Always switch to new buffer
+ // Buffer sizes: 4, 8, 16, 32, 64, 64, 64, 64
+ // First element in first buffer reserved
+ EXPECT_EQUAL(GrowthStats({ 3, 11, 27, 59, 123, 187,251, 315}), GrowStore().getGrowthStats(8));
+ // Resize current buffer if new buffer size would be less than 32
+ // Buffer sizes: 32, 36, 64, 64, 64, 64, 64, 64
+ // First element in first buffer reserved
+ EXPECT_EQUAL(GrowthStats({ 31, 67, 131, 195, 259,323,387,451}), GrowStore(32).getGrowthStats(8));
+}
+
int
Test::Main()
{
@@ -421,6 +475,7 @@ Test::Main()
requireThatMemoryStatsAreCalculated();
requireThatMemoryUsageIsCalculated();
requireThatWecanDisableElemHoldList();
+ requireThatBufferGrowthWorks();
TEST_DONE();
}
diff --git a/searchlib/src/vespa/searchlib/attribute/enumstorebase.cpp b/searchlib/src/vespa/searchlib/attribute/enumstorebase.cpp
index df3f9f18037..dbfd8744210 100644
--- a/searchlib/src/vespa/searchlib/attribute/enumstorebase.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/enumstorebase.cpp
@@ -28,7 +28,7 @@ EnumStoreBase::EnumBufferType::EnumBufferType()
}
size_t
-EnumStoreBase::EnumBufferType::calcClustersToAlloc(uint32_t bufferId, size_t sizeNeeded, uint64_t clusterRefSize, bool resizing) const
+EnumStoreBase::EnumBufferType::calcClustersToAlloc(uint32_t bufferId, size_t sizeNeeded, bool resizing) const
{
(void) resizing;
size_t reservedElements = getReservedElements(bufferId);
@@ -39,7 +39,7 @@ EnumStoreBase::EnumBufferType::calcClustersToAlloc(uint32_t bufferId, size_t siz
}
assert((usedElems % _clusterSize) == 0);
double growRatio = 1.5f;
- uint64_t maxSize = clusterRefSize * _clusterSize;
+ uint64_t maxSize = static_cast<uint64_t>(_maxClusters) * _clusterSize;
uint64_t newSize = usedElems - _deadElems + sizeNeeded;
if (usedElems != 0) {
newSize *= growRatio;
@@ -54,9 +54,9 @@ EnumStoreBase::EnumBufferType::calcClustersToAlloc(uint32_t bufferId, size_t siz
newSize = alignBufferSize(newSize);
assert((newSize % _clusterSize) == 0);
if (newSize <= maxSize) {
- return clusterRefSize;
+ return _maxClusters;
}
- failNewSize(newSize, clusterRefSize * _clusterSize);
+ failNewSize(newSize, maxSize);
return 0;
}
diff --git a/searchlib/src/vespa/searchlib/attribute/enumstorebase.h b/searchlib/src/vespa/searchlib/attribute/enumstorebase.h
index 08d17728bbf..cda6ab465b7 100644
--- a/searchlib/src/vespa/searchlib/attribute/enumstorebase.h
+++ b/searchlib/src/vespa/searchlib/attribute/enumstorebase.h
@@ -324,7 +324,7 @@ protected:
public:
EnumBufferType();
- virtual size_t calcClustersToAlloc(uint32_t bufferId, size_t sizeNeeded, uint64_t clusterRefSize, bool resizing) const override;
+ virtual size_t calcClustersToAlloc(uint32_t bufferId, size_t sizeNeeded, bool resizing) const override;
void setSizeNeededAndDead(uint64_t sizeNeeded, uint64_t deadElems) {
_minSizeNeeded = sizeNeeded;
diff --git a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping2.h b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping2.h
index 91be1143ab6..3a5d9c98c6f 100644
--- a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping2.h
+++ b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping2.h
@@ -27,7 +27,7 @@ private:
public:
MultiValueMapping2(uint32_t maxSmallArraySize,
const GrowStrategy &gs = GrowStrategy());
- MultiValueMapping2(uint32_t maxSmallArraySize, size_t minClusters, size_t maxClusters,
+ MultiValueMapping2(uint32_t maxSmallArraySize, size_t minClusters, size_t maxClusters, size_t numClustersForNewBuffer,
const GrowStrategy &gs = GrowStrategy());
virtual ~MultiValueMapping2();
ConstArrayRef get(uint32_t docId) const { return _store.get(_indices[docId]); }
diff --git a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping2.hpp b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping2.hpp
index 9cfaba960b3..b5653c3a046 100644
--- a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping2.hpp
+++ b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping2.hpp
@@ -15,9 +15,9 @@ MultiValueMapping2<EntryT,RefT>::MultiValueMapping2(uint32_t maxSmallArraySize,
}
template <typename EntryT, typename RefT>
-MultiValueMapping2<EntryT,RefT>::MultiValueMapping2(uint32_t maxSmallArraySize, size_t minClusters, size_t maxClusters, const GrowStrategy &gs)
+MultiValueMapping2<EntryT,RefT>::MultiValueMapping2(uint32_t maxSmallArraySize, size_t minClusters, size_t maxClusters, size_t numClustersForNewBuffer, const GrowStrategy &gs)
: MultiValueMapping2Base(gs, _store.getGenerationHolder()),
- _store(maxSmallArraySize, minClusters, maxClusters)
+ _store(maxSmallArraySize, minClusters, maxClusters, numClustersForNewBuffer)
{
}
diff --git a/searchlib/src/vespa/searchlib/datastore/array_store.h b/searchlib/src/vespa/searchlib/datastore/array_store.h
index 3a2d8b72988..45a9319b84b 100644
--- a/searchlib/src/vespa/searchlib/datastore/array_store.h
+++ b/searchlib/src/vespa/searchlib/datastore/array_store.h
@@ -51,7 +51,7 @@ private:
uint32_t _largeArrayTypeId;
using generation_t = vespalib::GenerationHandler::generation_t;
- void initArrayTypes(size_t minClusters, size_t maxClusters);
+ void initArrayTypes(size_t minClusters, size_t maxClusters, size_t numClustersForNewBuffer);
// 1-to-1 mapping between type ids and sizes for small arrays is enforced during initialization.
uint32_t getTypeId(size_t arraySize) const { return arraySize; }
size_t getArraySize(uint32_t typeId) const { return typeId; }
@@ -62,7 +62,7 @@ private:
public:
ArrayStore(uint32_t maxSmallArraySize);
- ArrayStore(uint32_t maxSmallArraySize, size_t minClusters, size_t maxClusters);
+ ArrayStore(uint32_t maxSmallArraySize, size_t minClusters, size_t maxClusters, size_t numClustersForNewBuffer);
~ArrayStore();
EntryRef add(const ConstArrayRef &array);
ConstArrayRef get(EntryRef ref) const;
diff --git a/searchlib/src/vespa/searchlib/datastore/array_store.hpp b/searchlib/src/vespa/searchlib/datastore/array_store.hpp
index ad341a2f297..125d9dce0ff 100644
--- a/searchlib/src/vespa/searchlib/datastore/array_store.hpp
+++ b/searchlib/src/vespa/searchlib/datastore/array_store.hpp
@@ -31,12 +31,12 @@ ArrayStore<EntryT, RefT>::LargeArrayType::cleanHold(void *buffer, uint64_t offse
template <typename EntryT, typename RefT>
void
-ArrayStore<EntryT, RefT>::initArrayTypes(size_t minClusters, size_t maxClusters)
+ArrayStore<EntryT, RefT>::initArrayTypes(size_t minClusters, size_t maxClusters, size_t numClustersForNewBuffer)
{
_largeArrayTypeId = _store.addType(&_largeArrayType);
assert(_largeArrayTypeId == 0);
for (uint32_t arraySize = 1; arraySize <= _maxSmallArraySize; ++arraySize) {
- _smallArrayTypes.push_back(std::make_unique<SmallArrayType>(arraySize, minClusters, maxClusters));
+ _smallArrayTypes.push_back(std::make_unique<SmallArrayType>(arraySize, minClusters, maxClusters, numClustersForNewBuffer));
uint32_t typeId = _store.addType(_smallArrayTypes.back().get());
assert(typeId == arraySize); // Enforce 1-to-1 mapping between type ids and sizes for small arrays
}
@@ -44,21 +44,19 @@ ArrayStore<EntryT, RefT>::initArrayTypes(size_t minClusters, size_t maxClusters)
template <typename EntryT, typename RefT>
ArrayStore<EntryT, RefT>::ArrayStore(uint32_t maxSmallArraySize)
- : ArrayStore<EntryT,RefT>(maxSmallArraySize, MIN_BUFFER_CLUSTERS, RefT::offsetSize())
+ : ArrayStore<EntryT,RefT>(maxSmallArraySize, MIN_BUFFER_CLUSTERS, RefT::offsetSize(), 0u)
{
}
template <typename EntryT, typename RefT>
-ArrayStore<EntryT, RefT>::ArrayStore(uint32_t maxSmallArraySize, size_t minClusters, size_t maxClusters)
+ArrayStore<EntryT, RefT>::ArrayStore(uint32_t maxSmallArraySize, size_t minClusters, size_t maxClusters, size_t numClustersForNewBuffer)
: _store(),
_maxSmallArraySize(maxSmallArraySize),
_smallArrayTypes(),
_largeArrayType(),
_largeArrayTypeId()
{
- maxClusters = std::min(maxClusters, RefT::offsetSize());
- minClusters = std::min(minClusters, maxClusters);
- initArrayTypes(minClusters, maxClusters);
+ initArrayTypes(minClusters, maxClusters, numClustersForNewBuffer);
_store.initActiveBuffers();
}
diff --git a/searchlib/src/vespa/searchlib/datastore/buffer_type.cpp b/searchlib/src/vespa/searchlib/datastore/buffer_type.cpp
index 5dbe7c052d6..6af02e31ef1 100644
--- a/searchlib/src/vespa/searchlib/datastore/buffer_type.cpp
+++ b/searchlib/src/vespa/searchlib/datastore/buffer_type.cpp
@@ -8,10 +8,12 @@ namespace datastore {
BufferTypeBase::BufferTypeBase(uint32_t clusterSize,
uint32_t minClusters,
- uint32_t maxClusters)
+ uint32_t maxClusters,
+ uint32_t numClustersForNewBuffer)
: _clusterSize(clusterSize),
_minClusters(std::min(minClusters, maxClusters)),
_maxClusters(maxClusters),
+ _numClustersForNewBuffer(std::min(numClustersForNewBuffer, maxClusters)),
_activeBuffers(0),
_holdBuffers(0),
_activeUsedElems(0),
@@ -21,6 +23,14 @@ BufferTypeBase::BufferTypeBase(uint32_t clusterSize,
}
+BufferTypeBase::BufferTypeBase(uint32_t clusterSize,
+ uint32_t minClusters,
+ uint32_t maxClusters)
+ : BufferTypeBase(clusterSize, minClusters, maxClusters, 0u)
+{
+}
+
+
BufferTypeBase::~BufferTypeBase(void)
{
assert(_activeBuffers == 0);
@@ -82,12 +92,16 @@ BufferTypeBase::onFree(size_t usedElems)
_holdUsedElems -= usedElems;
}
+void
+BufferTypeBase::clampMaxClusters(uint32_t maxClusters)
+{
+ _maxClusters = std::min(_maxClusters, maxClusters);
+ _minClusters = std::min(_minClusters, _maxClusters);
+ _numClustersForNewBuffer = std::min(_numClustersForNewBuffer, _maxClusters);
+};
size_t
-BufferTypeBase::calcClustersToAlloc(uint32_t bufferId,
- size_t sizeNeeded,
- uint64_t clusterRefSize,
- bool resizing) const
+BufferTypeBase::calcClustersToAlloc(uint32_t bufferId, size_t sizeNeeded, bool resizing) const
{
size_t reservedElements = getReservedElements(bufferId);
size_t usedElems = _activeUsedElems;
@@ -95,26 +109,15 @@ BufferTypeBase::calcClustersToAlloc(uint32_t bufferId,
usedElems += *_lastUsedElems;
}
assert((usedElems % _clusterSize) == 0);
- uint64_t maxClusters = std::numeric_limits<size_t>::max() / _clusterSize;
- uint64_t maxClusters2 = clusterRefSize;
- if (maxClusters > maxClusters2) {
- maxClusters = maxClusters2;
- }
- if (maxClusters > _maxClusters) {
- maxClusters = _maxClusters;
- }
- uint32_t minClusters = _minClusters;
- if (minClusters > maxClusters) {
- minClusters = maxClusters;
- }
size_t usedClusters = usedElems / _clusterSize;
size_t needClusters = (sizeNeeded + (resizing ? usedElems : reservedElements) + _clusterSize - 1) / _clusterSize;
- uint64_t wantClusters = usedClusters + minClusters;
+ size_t minClusters = _minClusters;
+ uint64_t wantClusters = usedClusters + std::max(minClusters, (resizing ? usedClusters : 0u));
if (wantClusters < needClusters) {
wantClusters = needClusters;
}
- if (wantClusters > maxClusters) {
- wantClusters = maxClusters;
+ if (wantClusters > _maxClusters) {
+ wantClusters = _maxClusters;
}
assert(wantClusters >= needClusters);
return wantClusters;
diff --git a/searchlib/src/vespa/searchlib/datastore/buffer_type.h b/searchlib/src/vespa/searchlib/datastore/buffer_type.h
index 0389e8b8a09..1889b37df11 100644
--- a/searchlib/src/vespa/searchlib/datastore/buffer_type.h
+++ b/searchlib/src/vespa/searchlib/datastore/buffer_type.h
@@ -15,6 +15,9 @@ protected:
uint32_t _clusterSize; // Number of elements in an allocation unit
uint32_t _minClusters; // Minimum number of clusters to allocate
uint32_t _maxClusters; // Maximum number of clusters to allocate
+ // Number of clusters needed before allocating a new buffer
+ // instead of just resizing the first one
+ uint32_t _numClustersForNewBuffer;
uint32_t _activeBuffers;
uint32_t _holdBuffers;
size_t _activeUsedElems; // used elements in all but last active buffer
@@ -36,6 +39,7 @@ public:
BufferTypeBase(const BufferTypeBase &rhs) = delete;
BufferTypeBase & operator=(const BufferTypeBase &rhs) = delete;
BufferTypeBase(uint32_t clusterSize, uint32_t minClusters, uint32_t maxClusters);
+ BufferTypeBase(uint32_t clusterSize, uint32_t minClusters, uint32_t maxClusters, uint32_t numClustersForNewBuffer);
virtual ~BufferTypeBase();
virtual void destroyElements(void *buffer, size_t numElements) = 0;
virtual void fallbackCopy(void *newBuffer, const void *oldBuffer, size_t numElements) = 0;
@@ -61,9 +65,13 @@ public:
*
* @return number of clusters to allocate for new buffer
*/
- virtual size_t calcClustersToAlloc(uint32_t bufferId, size_t sizeNeeded, uint64_t clusterRefSize, bool resizing) const;
+ virtual size_t calcClustersToAlloc(uint32_t bufferId, size_t sizeNeeded, bool resizing) const;
+
+ void clampMaxClusters(uint32_t maxClusters);
uint32_t getActiveBuffers() const { return _activeBuffers; }
+ uint32_t getMaxClusters() const { return _maxClusters; }
+ uint32_t getNumClustersForNewBuffer() const { return _numClustersForNewBuffer; }
};
@@ -79,7 +87,10 @@ public:
: BufferTypeBase(clusterSize, minClusters, maxClusters),
_emptyEntry()
{ }
-
+ BufferType(uint32_t clusterSize, uint32_t minClusters, uint32_t maxClusters, uint32_t numClustersForNewBuffer)
+ : BufferTypeBase(clusterSize, minClusters, maxClusters, numClustersForNewBuffer),
+ _emptyEntry()
+ { }
void destroyElements(void *buffer, size_t numElements) override;
void fallbackCopy(void *newBuffer, const void *oldBuffer, size_t numElements) override;
void initializeReservedElements(void *buffer, size_t reservedElements) override;
diff --git a/searchlib/src/vespa/searchlib/datastore/bufferstate.cpp b/searchlib/src/vespa/searchlib/datastore/bufferstate.cpp
index 5c85067bff5..9161fed94ee 100644
--- a/searchlib/src/vespa/searchlib/datastore/bufferstate.cpp
+++ b/searchlib/src/vespa/searchlib/datastore/bufferstate.cpp
@@ -51,7 +51,6 @@ void
BufferState::onActive(uint32_t bufferId, uint32_t typeId,
BufferTypeBase *typeHandler,
size_t sizeNeeded,
- size_t maxClusters,
void *&buffer)
{
assert(buffer == NULL);
@@ -71,7 +70,7 @@ BufferState::onActive(uint32_t bufferId, uint32_t typeId,
size_t reservedElements = typeHandler->getReservedElements(bufferId);
(void) reservedElements;
- size_t allocClusters = typeHandler->calcClustersToAlloc(bufferId, sizeNeeded, maxClusters, false);
+ size_t allocClusters = typeHandler->calcClustersToAlloc(bufferId, sizeNeeded, false);
size_t allocSize = allocClusters * typeHandler->getClusterSize();
assert(allocSize >= reservedElements + sizeNeeded);
_buffer.create(allocSize * typeHandler->elementSize()).swap(_buffer);
@@ -230,7 +229,6 @@ BufferState::disableElemHoldList(void)
void
BufferState::fallbackResize(uint32_t bufferId,
uint64_t sizeNeeded,
- size_t maxClusters,
void *&buffer,
Alloc &holdBuffer)
{
@@ -239,7 +237,6 @@ BufferState::fallbackResize(uint32_t bufferId,
assert(holdBuffer.get() == NULL);
size_t allocClusters = _typeHandler->calcClustersToAlloc(bufferId,
sizeNeeded,
- maxClusters,
true);
size_t allocSize = allocClusters * _typeHandler->getClusterSize();
assert(allocSize >= _usedElems + sizeNeeded);
diff --git a/searchlib/src/vespa/searchlib/datastore/bufferstate.h b/searchlib/src/vespa/searchlib/datastore/bufferstate.h
index 22f620ba7f6..c2fe3c2827f 100644
--- a/searchlib/src/vespa/searchlib/datastore/bufferstate.h
+++ b/searchlib/src/vespa/searchlib/datastore/bufferstate.h
@@ -81,13 +81,11 @@ public:
* @param typeId registered data type for buffer.
* @param typeHandler type handler for registered data type.
* @param sizeNeeded Number of elements needed to be free
- * @param maxSize number of clusters expressable via reference
- * type
* @param buffer start of buffer.
*/
void
onActive(uint32_t bufferId, uint32_t typeId, BufferTypeBase *typeHandler,
- size_t sizeNeeded, size_t maxSize, void *&buffer);
+ size_t sizeNeeded, void *&buffer);
/**
* Transition from ACTIVE to HOLD state.
@@ -156,7 +154,7 @@ public:
size_t getExtraHoldBytes() const { return _extraHoldBytes; }
bool getCompacting() const { return _compacting; }
void setCompacting() { _compacting = true; }
- void fallbackResize(uint32_t bufferId, uint64_t sizeNeeded, size_t maxClusters, void *&buffer, Alloc &holdBuffer);
+ void fallbackResize(uint32_t bufferId, uint64_t sizeNeeded, void *&buffer, Alloc &holdBuffer);
bool isActive(uint32_t typeId) const {
return ((_state == ACTIVE) && (_typeId == typeId));
diff --git a/searchlib/src/vespa/searchlib/datastore/datastorebase.cpp b/searchlib/src/vespa/searchlib/datastore/datastorebase.cpp
index 435d9a1423b..4753a997157 100644
--- a/searchlib/src/vespa/searchlib/datastore/datastorebase.cpp
+++ b/searchlib/src/vespa/searchlib/datastore/datastorebase.cpp
@@ -108,12 +108,41 @@ DataStoreBase::switchActiveBuffer(uint32_t typeId, size_t sizeNeeded)
// start using next buffer
activeBufferId = nextBufferId(activeBufferId);
} while (!_states[activeBufferId].isFree());
- onActive(activeBufferId, typeId, sizeNeeded, _maxClusters);
+ onActive(activeBufferId, typeId, sizeNeeded);
_activeBufferIds[typeId] = activeBufferId;
}
void
+DataStoreBase::switchOrGrowActiveBuffer(uint32_t typeId, size_t sizeNeeded)
+{
+ auto typeHandler = _typeHandlers[typeId];
+ uint32_t clusterSize = typeHandler->getClusterSize();
+ size_t numClustersForNewBuffer = typeHandler->getNumClustersForNewBuffer();
+ size_t numEntriesForNewBuffer = numClustersForNewBuffer * clusterSize;
+ uint32_t bufferId = _activeBufferIds[typeId];
+ if (sizeNeeded + _states[bufferId].size() >= numEntriesForNewBuffer) {
+ // Don't try to resize existing buffer, new buffer will be large enough
+ switchActiveBuffer(typeId, sizeNeeded);
+ } else {
+ uint32_t oldBufferId = bufferId;
+ do {
+ bufferId = nextBufferId(bufferId);
+ } while (!_states[bufferId].isFree());
+ size_t allocClusters = typeHandler->calcClustersToAlloc(bufferId, sizeNeeded, false);
+ if (allocClusters < numClustersForNewBuffer) {
+ // Resize existing buffer
+ fallbackResize(oldBufferId, sizeNeeded);
+ } else {
+ // start using next buffer
+ onActive(bufferId, typeId, sizeNeeded);
+ _activeBufferIds[typeId] = bufferId;
+ }
+ }
+}
+
+
+void
DataStoreBase::initActiveBuffers(void)
{
uint32_t numTypes = _activeBufferIds.size();
@@ -123,7 +152,7 @@ DataStoreBase::initActiveBuffers(void)
// start using next buffer
activeBufferId = nextBufferId(activeBufferId);
}
- onActive(activeBufferId, typeId, 0u, _maxClusters);
+ onActive(activeBufferId, typeId, 0u);
_activeBufferIds[typeId] = activeBufferId;
}
}
@@ -134,6 +163,7 @@ DataStoreBase::addType(BufferTypeBase *typeHandler)
{
uint32_t typeId = _activeBufferIds.size();
assert(typeId == _typeHandlers.size());
+ typeHandler->clampMaxClusters(_maxClusters);
_activeBufferIds.push_back(0);
_typeHandlers.push_back(typeHandler);
_freeListLists.push_back(BufferState::FreeListList());
@@ -330,8 +360,7 @@ DataStoreBase::getMemStats(void) const
void
DataStoreBase::onActive(uint32_t bufferId, uint32_t typeId,
- size_t sizeNeeded,
- size_t maxClusters)
+ size_t sizeNeeded)
{
assert(typeId < _typeHandlers.size());
assert(bufferId < _numBuffers);
@@ -339,7 +368,6 @@ DataStoreBase::onActive(uint32_t bufferId, uint32_t typeId,
state.onActive(bufferId, typeId,
_typeHandlers[typeId],
sizeNeeded,
- maxClusters,
_buffers[bufferId]);
enableFreeList(bufferId);
}
@@ -382,7 +410,6 @@ DataStoreBase::fallbackResize(uint32_t bufferId, uint64_t sizeNeeded)
size_t elementSize = state.getTypeHandler()->elementSize();
state.fallbackResize(bufferId,
sizeNeeded,
- _maxClusters,
_buffers[bufferId],
toHoldBuffer);
GenerationHeldBase::UP
diff --git a/searchlib/src/vespa/searchlib/datastore/datastorebase.h b/searchlib/src/vespa/searchlib/datastore/datastorebase.h
index f64ff4b3c8a..cefd53132cb 100644
--- a/searchlib/src/vespa/searchlib/datastore/datastorebase.h
+++ b/searchlib/src/vespa/searchlib/datastore/datastorebase.h
@@ -205,7 +205,7 @@ public:
if (__builtin_expect(sizeNeeded >
_states[_activeBufferIds[typeId]].remaining(),
false)) {
- switchActiveBuffer(typeId, sizeNeeded);
+ switchOrGrowActiveBuffer(typeId, sizeNeeded);
}
}
@@ -227,6 +227,8 @@ public:
void
switchActiveBuffer(uint32_t typeId, size_t sizeNeeded);
+ void switchOrGrowActiveBuffer(uint32_t typeId, size_t sizeNeeded);
+
MemoryUsage getMemoryUsage() const;
/**
@@ -365,13 +367,9 @@ public:
* @param bufferId Id of buffer to be active.
* @param typeId registered data type for buffer.
* @param sizeNeeded Number of elements needed to be free
- * @param maxSize number of clusters expressable via reference
- * type
*/
void
- onActive(uint32_t bufferId, uint32_t typeId,
- size_t sizeNeeded,
- size_t maxSize);
+ onActive(uint32_t bufferId, uint32_t typeId, size_t sizeNeeded);
uint32_t
getTypeId(uint32_t bufferId) const