aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib/src
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2021-08-12 16:08:42 +0200
committerGitHub <noreply@github.com>2021-08-12 16:08:42 +0200
commit07446ba73633a2cf392b844f5bb02aac032fb397 (patch)
treeab4a6f62ee25b3fe4148c91fe528dae72dc79277 /searchlib/src
parent906f75648e6f0a596c791d71812a6636884adf13 (diff)
parent3efc9cfdde773167f3a8385dc7ccf9b7235d3acb (diff)
Merge pull request #18723 from vespa-engine/balder/add-swapable-attribute-option
Balder/add swapable attribute option
Diffstat (limited to 'searchlib/src')
-rw-r--r--searchlib/src/tests/attribute/attributemanager/attributemanager_test.cpp110
-rw-r--r--searchlib/src/tests/attribute/tensorattribute/tensorattribute_test.cpp23
-rw-r--r--searchlib/src/tests/tensor/dense_tensor_store/dense_tensor_store_test.cpp8
-rw-r--r--searchlib/src/vespa/searchlib/attribute/attributevector.h16
-rw-r--r--searchlib/src/vespa/searchlib/attribute/configconverter.cpp1
-rw-r--r--searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.cpp13
-rw-r--r--searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.h2
-rw-r--r--searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp15
-rw-r--r--searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h6
9 files changed, 97 insertions, 97 deletions
diff --git a/searchlib/src/tests/attribute/attributemanager/attributemanager_test.cpp b/searchlib/src/tests/attribute/attributemanager/attributemanager_test.cpp
index 721e7e1c805..877b5b9e427 100644
--- a/searchlib/src/tests/attribute/attributemanager/attributemanager_test.cpp
+++ b/searchlib/src/tests/attribute/attributemanager/attributemanager_test.cpp
@@ -20,43 +20,13 @@ using namespace search::attribute;
using std::shared_ptr;
using vespalib::stringref;
-typedef BasicType BT;
-typedef CollectionType CT;
-typedef AttributeVector::SP AVSP;
+using BT = BasicType;
+using CT = CollectionType;
+using AVSP = AttributeVector::SP;
namespace search {
-class AttributeManagerTest : public vespalib::TestApp
-{
-private:
- void verifyLoad(AttributeVector & v);
- void testLoad();
- void testGuards();
- void testConfigConvert();
- void testContext();
- void can_get_readable_attribute_vector_by_name();
-
- bool
- assertDataType(BT::Type exp,
- AttributesConfig::Attribute::Datatype in);
-
- bool
- assertCollectionType(CollectionType exp,
- AttributesConfig::Attribute::Collectiontype in,
- bool removeIfZ = false,
- bool createIfNe = false);
-
-public:
- AttributeManagerTest()
- {
- }
- int Main() override;
-};
-
-
-typedef MultiValueNumericAttribute< IntegerAttributeTemplate<int32_t>,
- multivalue::Value<int32_t> >
-TestAttributeBase;
+using TestAttributeBase = MultiValueNumericAttribute< IntegerAttributeTemplate<int32_t>, multivalue::Value<int32_t> >;
class TestAttribute : public TestAttributeBase
{
@@ -73,8 +43,7 @@ public:
};
-void
-AttributeManagerTest::testGuards()
+TEST("Test attribute guards")
{
AttributeVector::SP vec(new TestAttribute("mvint") );
TestAttribute * v = static_cast<TestAttribute *> (vec.get());
@@ -134,7 +103,7 @@ AttributeManagerTest::testGuards()
void
-AttributeManagerTest::verifyLoad(AttributeVector & v)
+verifyLoad(AttributeVector & v)
{
EXPECT_TRUE( !v.isLoaded() );
EXPECT_TRUE( v.load() );
@@ -143,8 +112,7 @@ AttributeManagerTest::verifyLoad(AttributeVector & v)
}
-void
-AttributeManagerTest::testLoad()
+TEST("Test loading of attributes")
{
{
TestAttributeBase v("mvint");
@@ -172,14 +140,14 @@ AttributeManagerTest::testLoad()
verifyLoad(v);
}
{
- AttributeVector::Config config(BT::INT32,
+ Config config(BT::INT32,
CollectionType::ARRAY);
TestAttributeBase v("mvint", config);
verifyLoad(v);
}
{
AttributeManager manager;
- AttributeVector::Config config(BT::INT32,
+ Config config(BT::INT32,
CollectionType::ARRAY);
EXPECT_TRUE(manager.addVector("mvint", config));
AttributeManager::AttributeList list;
@@ -193,7 +161,7 @@ AttributeManagerTest::testLoad()
bool
-AttributeManagerTest::assertDataType(BT::Type exp, AttributesConfig::Attribute::Datatype in)
+assertDataType(BT::Type exp, AttributesConfig::Attribute::Datatype in)
{
AttributesConfig::Attribute a;
a.datatype = in;
@@ -202,25 +170,22 @@ AttributeManagerTest::assertDataType(BT::Type exp, AttributesConfig::Attribute::
bool
-AttributeManagerTest::
assertCollectionType(CollectionType exp, AttributesConfig::Attribute::Collectiontype in,
- bool removeIfZ, bool createIfNe)
+ bool removeIfZ = false, bool createIfNe = false)
{
AttributesConfig::Attribute a;
a.collectiontype = in;
a.removeifzero = removeIfZ;
a.createifnonexistent = createIfNe;
- AttributeVector::Config out = ConfigConverter::convert(a);
+ Config out = ConfigConverter::convert(a);
return EXPECT_EQUAL(exp.type(), out.collectionType().type()) &&
EXPECT_EQUAL(exp.removeIfZero(), out.collectionType().removeIfZero()) &&
EXPECT_EQUAL(exp.createIfNonExistant(), out.collectionType().createIfNonExistant());
}
-void
-AttributeManagerTest::testConfigConvert()
+TEST("require that config can be converted")
{
- // typedef AttributeVector::Config AVC;
typedef BT AVBT;
typedef CollectionType AVCT;
using CACA = AttributesConfig::Attribute;
@@ -271,11 +236,17 @@ AttributeManagerTest::testConfigConvert()
a.ismutable = true;
EXPECT_TRUE(CC::convert(a).isMutable());
}
+ {
+ CACA a;
+ EXPECT_TRUE(!CC::convert(a).paged());
+ a.paged = true;
+ EXPECT_TRUE(CC::convert(a).paged());
+ }
{ // tensor
CACA a;
a.datatype = CACAD::TENSOR;
a.tensortype = "tensor(x[5])";
- AttributeVector::Config out = ConfigConverter::convert(a);
+ Config out = ConfigConverter::convert(a);
EXPECT_EQUAL("tensor(x[5])", out.tensorType().to_spec());
}
{ // distance metric (default)
@@ -334,8 +305,7 @@ bool gt_attribute(const attribute::IAttributeVector * a, const attribute::IAttri
return a->getName() < b->getName();
}
-void
-AttributeManagerTest::testContext()
+TEST("test the attribute context")
{
std::vector<AVSP> attrs;
// create various attributes vectors
@@ -370,13 +340,13 @@ AttributeManagerTest::testContext()
}
for (uint32_t i = 0; i < 2; ++i) {
- EXPECT_TRUE(first->getAttribute("sint32") != NULL);
- EXPECT_TRUE(first->getAttribute("aint32") != NULL);
- EXPECT_TRUE(first->getAttribute("wsint32") != NULL);
- EXPECT_TRUE(first->getAttributeStableEnum("wsint32") != NULL);
+ EXPECT_TRUE(first->getAttribute("sint32") != nullptr);
+ EXPECT_TRUE(first->getAttribute("aint32") != nullptr);
+ EXPECT_TRUE(first->getAttribute("wsint32") != nullptr);
+ EXPECT_TRUE(first->getAttributeStableEnum("wsint32") != nullptr);
}
- EXPECT_TRUE(first->getAttribute("foo") == NULL);
- EXPECT_TRUE(first->getAttribute("bar") == NULL);
+ EXPECT_TRUE(first->getAttribute("foo") == nullptr);
+ EXPECT_TRUE(first->getAttribute("bar") == nullptr);
// one generation guard taken per attribute asked for
for (uint32_t i = 0; i < attrs.size(); ++i) {
@@ -388,10 +358,10 @@ AttributeManagerTest::testContext()
{
IAttributeContext::UP second = manager.createContext();
- EXPECT_TRUE(second->getAttribute("sint32") != NULL);
- EXPECT_TRUE(second->getAttribute("aint32") != NULL);
- EXPECT_TRUE(second->getAttribute("wsint32") != NULL);
- EXPECT_TRUE(second->getAttributeStableEnum("wsint32") != NULL);
+ EXPECT_TRUE(second->getAttribute("sint32") != nullptr);
+ EXPECT_TRUE(second->getAttribute("aint32") != nullptr);
+ EXPECT_TRUE(second->getAttribute("wsint32") != nullptr);
+ EXPECT_TRUE(second->getAttributeStableEnum("wsint32") != nullptr);
// two generation guards taken per attribute asked for
for (uint32_t i = 0; i < attrs.size(); ++i) {
@@ -428,8 +398,7 @@ AttributeManagerTest::testContext()
}
}
-void
-AttributeManagerTest::can_get_readable_attribute_vector_by_name()
+TEST("require that we can get readable attribute by name")
{
auto attr = AttributeFactory::createAttribute("cool_attr", Config(BT::INT32, CT::SINGLE));
// Ensure there's something to actually load, or fetching the attribute will throw.
@@ -443,20 +412,7 @@ AttributeManagerTest::can_get_readable_attribute_vector_by_name()
EXPECT_TRUE(av.get() == nullptr);
}
-int AttributeManagerTest::Main()
-{
- TEST_INIT("attributemanager_test");
-
- testLoad();
- testGuards();
- testConfigConvert();
- testContext();
- can_get_readable_attribute_vector_by_name();
-
- TEST_DONE();
-}
-
} // namespace search
-TEST_APPHOOK(search::AttributeManagerTest);
+TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/searchlib/src/tests/attribute/tensorattribute/tensorattribute_test.cpp b/searchlib/src/tests/attribute/tensorattribute/tensorattribute_test.cpp
index b27c26d1139..605fcb538d6 100644
--- a/searchlib/src/tests/attribute/tensorattribute/tensorattribute_test.cpp
+++ b/searchlib/src/tests/attribute/tensorattribute/tensorattribute_test.cpp
@@ -26,6 +26,7 @@
#include <vespa/vespalib/io/fileutil.h>
#include <vespa/vespalib/test/insertion_operators.h>
#include <vespa/vespalib/testkit/test_kit.h>
+#include <vespa/vespalib/util/mmap_file_allocator_factory.h>
#include <vespa/searchlib/util/bufferwriter.h>
#include <vespa/log/log.h>
@@ -256,6 +257,7 @@ struct FixtureTraits {
bool use_direct_tensor_attribute = false;
bool enable_hnsw_index = false;
bool use_mock_index = false;
+ bool use_mmap_file_allocator = false;
FixtureTraits dense() && {
use_dense_tensor_attribute = true;
@@ -263,6 +265,11 @@ struct FixtureTraits {
return *this;
}
+ FixtureTraits mmap_file_allocator() && {
+ use_mmap_file_allocator = true;
+ return *this;
+ }
+
FixtureTraits hnsw() && {
use_dense_tensor_attribute = true;
enable_hnsw_index = true;
@@ -327,6 +334,9 @@ struct Fixture {
if (_cfg.tensorType().is_dense()) {
_denseTensors = true;
}
+ if (_traits.use_mmap_file_allocator) {
+ _cfg.setPaged(true);
+ }
if (_traits.use_mock_index) {
_index_factory = std::make_unique<MockNearestNeighborIndexFactory>();
} else {
@@ -1000,4 +1010,17 @@ TEST_F("NN blueprint handles strong filter triggering brute force search", Neare
EXPECT_FALSE(bp->may_approximate());
}
+TEST("Dense tensor attribute with paged flag uses mmap file allocator")
+{
+ vespalib::string basedir("mmap-file-allocator-factory-dir");
+ vespalib::alloc::MmapFileAllocatorFactory::instance().setup(basedir);
+ {
+ Fixture f(vec_2d_spec, FixtureTraits().dense().mmap_file_allocator());
+ vespalib::string allocator_dir(basedir + "/0.my_attr");
+ EXPECT_TRUE(vespalib::isDirectory(allocator_dir));
+ }
+ vespalib::alloc::MmapFileAllocatorFactory::instance().setup("");
+ vespalib::rmdir(basedir, true);
+}
+
TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/searchlib/src/tests/tensor/dense_tensor_store/dense_tensor_store_test.cpp b/searchlib/src/tests/tensor/dense_tensor_store/dense_tensor_store_test.cpp
index eb8d89edc07..75e231a815c 100644
--- a/searchlib/src/tests/tensor/dense_tensor_store/dense_tensor_store_test.cpp
+++ b/searchlib/src/tests/tensor/dense_tensor_store/dense_tensor_store_test.cpp
@@ -1,5 +1,8 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/log/log.h>
+LOG_SETUP("dense_tensor_store_test");
#include <vespa/vespalib/testkit/test_kit.h>
+#include <vespa/vespalib/util/memory_allocator.h>
#include <vespa/searchlib/tensor/dense_tensor_store.h>
#include <vespa/eval/eval/simple_value.h>
#include <vespa/eval/eval/tensor_spec.h>
@@ -7,9 +10,6 @@
#include <vespa/eval/eval/value_type.h>
#include <vespa/eval/eval/test/value_compare.h>
-#include <vespa/log/log.h>
-LOG_SETUP("dense_tensor_store_test");
-
using search::tensor::DenseTensorStore;
using vespalib::eval::SimpleValue;
using vespalib::eval::TensorSpec;
@@ -28,7 +28,7 @@ struct Fixture
{
DenseTensorStore store;
Fixture(const vespalib::string &tensorType)
- : store(ValueType::from_spec(tensorType))
+ : store(ValueType::from_spec(tensorType), {})
{}
void assertSetAndGetTensor(const TensorSpec &tensorSpec) {
Value::UP expTensor = makeTensor(tensorSpec);
diff --git a/searchlib/src/vespa/searchlib/attribute/attributevector.h b/searchlib/src/vespa/searchlib/attribute/attributevector.h
index 3c27f00a022..99b0c923c90 100644
--- a/searchlib/src/vespa/searchlib/attribute/attributevector.h
+++ b/searchlib/src/vespa/searchlib/attribute/attributevector.h
@@ -282,6 +282,14 @@ public:
virtual IExtendAttribute * getExtendInterface();
+ /**
+ * Returns the number of readers holding a generation guard.
+ * Should be called by the writer thread.
+ **/
+ uint32_t getGenerationRefCount(generation_t gen) const {
+ return _genHandler.getGenerationRefCount(gen);
+ }
+
protected:
/**
* Called when a new document has been added, but only for
@@ -291,14 +299,6 @@ protected:
**/
virtual bool onAddDoc(DocId) { return false; }
- /**
- * Returns the number of readers holding a generation guard.
- * Should be called by the writer thread.
- */
- uint32_t getGenerationRefCount(generation_t gen) const {
- return _genHandler.getGenerationRefCount(gen);
- }
-
const GenerationHandler & getGenerationHandler() const {
return _genHandler;
}
diff --git a/searchlib/src/vespa/searchlib/attribute/configconverter.cpp b/searchlib/src/vespa/searchlib/attribute/configconverter.cpp
index 6387edc588b..625502ee32b 100644
--- a/searchlib/src/vespa/searchlib/attribute/configconverter.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/configconverter.cpp
@@ -108,6 +108,7 @@ ConfigConverter::convert(const AttributesConfig::Attribute & cfg)
retval.setIsFilter(cfg.enableonlybitvector);
retval.setFastAccess(cfg.fastaccess);
retval.setMutable(cfg.ismutable);
+ retval.setPaged(cfg.paged);
predicateParams.setArity(cfg.arity);
predicateParams.setBounds(cfg.lowerbound, cfg.upperbound);
predicateParams.setDensePostingListThreshold(cfg.densepostinglistthreshold);
diff --git a/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.cpp b/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.cpp
index be15967ab10..d0943b372be 100644
--- a/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.cpp
@@ -10,6 +10,8 @@
#include <vespa/searchlib/attribute/load_utils.h>
#include <vespa/searchlib/attribute/readerbase.h>
#include <vespa/vespalib/data/slime/inserter.h>
+#include <vespa/vespalib/util/memory_allocator.h>
+#include <vespa/vespalib/util/mmap_file_allocator_factory.h>
#include <vespa/log/log.h>
LOG_SETUP(".searchlib.tensor.dense_tensor_attribute");
@@ -72,6 +74,15 @@ can_use_index_save_file(const search::attribute::Config &config, const search::a
return true;
}
+std::unique_ptr<vespalib::alloc::MemoryAllocator>
+make_memory_allocator(const vespalib::string& name, bool swappable)
+{
+ if (swappable) {
+ return vespalib::alloc::MmapFileAllocatorFactory::instance().make_memory_allocator(name);
+ }
+ return {};
+}
+
}
void
@@ -114,7 +125,7 @@ DenseTensorAttribute::memory_usage() const
DenseTensorAttribute::DenseTensorAttribute(vespalib::stringref baseFileName, const Config& cfg,
const NearestNeighborIndexFactory& index_factory)
: TensorAttribute(baseFileName, cfg, _denseTensorStore),
- _denseTensorStore(cfg.tensorType()),
+ _denseTensorStore(cfg.tensorType(), make_memory_allocator(getName(), cfg.paged())),
_index()
{
if (cfg.hnsw_index_params().has_value()) {
diff --git a/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.h b/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.h
index 0884b776ca5..7eb8f2510f7 100644
--- a/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.h
+++ b/searchlib/src/vespa/searchlib/tensor/dense_tensor_attribute.h
@@ -29,7 +29,7 @@ private:
public:
DenseTensorAttribute(vespalib::stringref baseFileName, const Config& cfg,
const NearestNeighborIndexFactory& index_factory = DefaultNearestNeighborIndexFactory());
- virtual ~DenseTensorAttribute();
+ ~DenseTensorAttribute() override;
// Implements AttributeVector and ITensorAttribute
uint32_t clearDoc(DocId docId) override;
void setTensor(DocId docId, const vespalib::eval::Value &tensor) override;
diff --git a/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp b/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp
index e6da839da2e..13796d35dec 100644
--- a/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp
@@ -40,8 +40,9 @@ DenseTensorStore::TensorSizeCalc::alignedSize() const
return my_align(bufSize(), DENSE_TENSOR_ALIGNMENT);
}
-DenseTensorStore::BufferType::BufferType(const TensorSizeCalc &tensorSizeCalc)
- : vespalib::datastore::BufferType<char>(tensorSizeCalc.alignedSize(), MIN_BUFFER_ARRAYS, RefType::offsetSize())
+DenseTensorStore::BufferType::BufferType(const TensorSizeCalc &tensorSizeCalc, std::unique_ptr<vespalib::alloc::MemoryAllocator> allocator)
+ : vespalib::datastore::BufferType<char>(tensorSizeCalc.alignedSize(), MIN_BUFFER_ARRAYS, RefType::offsetSize()),
+ _allocator(std::move(allocator))
{}
DenseTensorStore::BufferType::~BufferType() = default;
@@ -53,11 +54,17 @@ DenseTensorStore::BufferType::cleanHold(void *buffer, size_t offset,
memset(static_cast<char *>(buffer) + offset, 0, numElems);
}
-DenseTensorStore::DenseTensorStore(const ValueType &type)
+const vespalib::alloc::MemoryAllocator*
+DenseTensorStore::BufferType::get_memory_allocator() const
+{
+ return _allocator.get();
+}
+
+DenseTensorStore::DenseTensorStore(const ValueType &type, std::unique_ptr<vespalib::alloc::MemoryAllocator> allocator)
: TensorStore(_concreteStore),
_concreteStore(),
_tensorSizeCalc(type),
- _bufferType(_tensorSizeCalc),
+ _bufferType(_tensorSizeCalc, std::move(allocator)),
_type(type),
_emptySpace()
{
diff --git a/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h b/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h
index 638f602d613..dad28642e67 100644
--- a/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h
+++ b/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h
@@ -36,10 +36,12 @@ public:
class BufferType : public vespalib::datastore::BufferType<char>
{
using CleanContext = vespalib::datastore::BufferType<char>::CleanContext;
+ std::unique_ptr<vespalib::alloc::MemoryAllocator> _allocator;
public:
- BufferType(const TensorSizeCalc &tensorSizeCalc);
+ BufferType(const TensorSizeCalc &tensorSizeCalc, std::unique_ptr<vespalib::alloc::MemoryAllocator> allocator);
~BufferType() override;
void cleanHold(void *buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx) override;
+ const vespalib::alloc::MemoryAllocator* get_memory_allocator() const override;
};
private:
DataStoreType _concreteStore;
@@ -55,7 +57,7 @@ private:
setDenseTensor(const TensorType &tensor);
public:
- DenseTensorStore(const ValueType &type);
+ DenseTensorStore(const ValueType &type, std::unique_ptr<vespalib::alloc::MemoryAllocator> allocator);
~DenseTensorStore() override;
const ValueType &type() const { return _type; }