diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2021-08-12 16:08:42 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-12 16:08:42 +0200 |
commit | 07446ba73633a2cf392b844f5bb02aac032fb397 (patch) | |
tree | ab4a6f62ee25b3fe4148c91fe528dae72dc79277 /searchlib/src | |
parent | 906f75648e6f0a596c791d71812a6636884adf13 (diff) | |
parent | 3efc9cfdde773167f3a8385dc7ccf9b7235d3acb (diff) |
Merge pull request #18723 from vespa-engine/balder/add-swapable-attribute-option
Balder/add swapable attribute option
Diffstat (limited to 'searchlib/src')
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; } |