summaryrefslogtreecommitdiffstats
path: root/searchlib/src
diff options
context:
space:
mode:
Diffstat (limited to 'searchlib/src')
-rw-r--r--searchlib/src/tests/attribute/attribute_test.cpp44
-rw-r--r--searchlib/src/tests/attribute/extendattributes/extendattribute.cpp176
-rw-r--r--searchlib/src/tests/attribute/multi_value_mapping/multi_value_mapping_test.cpp24
-rw-r--r--searchlib/src/tests/memoryindex/field_index/field_index_test.cpp36
-rw-r--r--searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp4
-rw-r--r--searchlib/src/tests/predicate/document_features_store_test.cpp14
-rw-r--r--searchlib/src/vespa/searchlib/attribute/attributevector.h3
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h14
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multi_value_mapping.hpp36
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multi_value_mapping_read_view.h6
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postinglistattribute.h2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postingstore.cpp12
-rw-r--r--searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp2
-rw-r--r--searchlib/src/vespa/searchlib/memoryindex/feature_store.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/memoryindex/feature_store.h3
-rw-r--r--searchlib/src/vespa/searchlib/memoryindex/field_index.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/memoryindex/word_store.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/predicate/document_features_store.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/predicate/predicate_interval_store.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/predicate/simple_index.hpp6
-rw-r--r--searchlib/src/vespa/searchlib/tensor/CMakeLists.txt1
-rw-r--r--searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp10
-rw-r--r--searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h2
-rw-r--r--searchlib/src/vespa/searchlib/tensor/direct_tensor_store.cpp6
-rw-r--r--searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h4
-rw-r--r--searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.cpp22
-rw-r--r--searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.h8
-rw-r--r--searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.cpp30
-rw-r--r--searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.h8
-rw-r--r--searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.cpp181
-rw-r--r--searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.h54
34 files changed, 536 insertions, 192 deletions
diff --git a/searchlib/src/tests/attribute/attribute_test.cpp b/searchlib/src/tests/attribute/attribute_test.cpp
index 7eb43faac18..d2d3ccaad23 100644
--- a/searchlib/src/tests/attribute/attribute_test.cpp
+++ b/searchlib/src/tests/attribute/attribute_test.cpp
@@ -912,8 +912,8 @@ AttributeTest::testSingle()
cfg.setFastSearch(true);
AttributePtr ptr = createAttribute("sv-post-int32", cfg);
ptr->updateStat(true);
- EXPECT_EQ(339020u, ptr->getStatus().getAllocated());
- EXPECT_EQ(101852u, ptr->getStatus().getUsed());
+ EXPECT_EQ(338972u, ptr->getStatus().getAllocated());
+ EXPECT_EQ(101492u, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testSingle<IntegerAttribute, AttributeVector::largeint_t, int32_t>(ptr, values);
}
@@ -934,8 +934,8 @@ AttributeTest::testSingle()
cfg.setFastSearch(true);
AttributePtr ptr = createAttribute("sv-post-float", cfg);
ptr->updateStat(true);
- EXPECT_EQ(339020, ptr->getStatus().getAllocated());
- EXPECT_EQ(101852u, ptr->getStatus().getUsed());
+ EXPECT_EQ(338972u, ptr->getStatus().getAllocated());
+ EXPECT_EQ(101492u, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testSingle<FloatingPointAttribute, double, float>(ptr, values);
}
@@ -947,8 +947,8 @@ AttributeTest::testSingle()
{
AttributePtr ptr = createAttribute("sv-string", Config(BasicType::STRING, CollectionType::SINGLE));
ptr->updateStat(true);
- EXPECT_EQ(117256u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
- EXPECT_EQ(53240u + sizeof_large_string_entry, ptr->getStatus().getUsed());
+ EXPECT_EQ(116528u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
+ EXPECT_EQ(52760u + sizeof_large_string_entry, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testSingle<StringAttribute, string, string>(ptr, values);
}
@@ -957,8 +957,8 @@ AttributeTest::testSingle()
cfg.setFastSearch(true);
AttributePtr ptr = createAttribute("sv-fs-string", cfg);
ptr->updateStat(true);
- EXPECT_EQ(345624u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
- EXPECT_EQ(105176u + sizeof_large_string_entry, ptr->getStatus().getUsed());
+ EXPECT_EQ(344848u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
+ EXPECT_EQ(104408u + sizeof_large_string_entry, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testSingle<StringAttribute, string, string>(ptr, values);
}
@@ -1089,8 +1089,8 @@ AttributeTest::testArray()
{
AttributePtr ptr = createAttribute("a-int32", Config(BasicType::INT32, CollectionType::ARRAY));
ptr->updateStat(true);
- EXPECT_EQ(512056u, ptr->getStatus().getAllocated());
- EXPECT_EQ(504392u, ptr->getStatus().getUsed());
+ EXPECT_EQ(487480u, ptr->getStatus().getAllocated());
+ EXPECT_EQ(479720u, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testArray<IntegerAttribute, AttributeVector::largeint_t>(ptr, values);
}
@@ -1099,8 +1099,8 @@ AttributeTest::testArray()
cfg.setFastSearch(true);
AttributePtr ptr = createAttribute("flags", cfg);
ptr->updateStat(true);
- EXPECT_EQ(512056u, ptr->getStatus().getAllocated());
- EXPECT_EQ(504392u, ptr->getStatus().getUsed());
+ EXPECT_EQ(487480u, ptr->getStatus().getAllocated());
+ EXPECT_EQ(479720u, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testArray<IntegerAttribute, AttributeVector::largeint_t>(ptr, values);
}
@@ -1109,8 +1109,8 @@ AttributeTest::testArray()
cfg.setFastSearch(true);
AttributePtr ptr = createAttribute("a-fs-int32", cfg);
ptr->updateStat(true);
- EXPECT_EQ(868788u, ptr->getStatus().getAllocated());
- EXPECT_EQ(606264u, ptr->getStatus().getUsed());
+ EXPECT_EQ(844116u, ptr->getStatus().getAllocated());
+ EXPECT_EQ(581232u, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testArray<IntegerAttribute, AttributeVector::largeint_t>(ptr, values);
}
@@ -1128,8 +1128,8 @@ AttributeTest::testArray()
cfg.setFastSearch(true);
AttributePtr ptr = createAttribute("a-fs-float", cfg);
ptr->updateStat(true);
- EXPECT_EQ(868788u, ptr->getStatus().getAllocated());
- EXPECT_EQ(606264u, ptr->getStatus().getUsed());
+ EXPECT_EQ(844116u, ptr->getStatus().getAllocated());
+ EXPECT_EQ(581232u, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testArray<FloatingPointAttribute, double>(ptr, values);
}
@@ -1140,8 +1140,8 @@ AttributeTest::testArray()
{
AttributePtr ptr = createAttribute("a-string", Config(BasicType::STRING, CollectionType::ARRAY));
ptr->updateStat(true);
- EXPECT_EQ(625088u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
- EXPECT_EQ(557632u + sizeof_large_string_entry, ptr->getStatus().getUsed());
+ EXPECT_EQ(599784u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
+ EXPECT_EQ(532480u + sizeof_large_string_entry, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testArray<StringAttribute, string>(ptr, values);
}
@@ -1150,8 +1150,8 @@ AttributeTest::testArray()
cfg.setFastSearch(true);
AttributePtr ptr = createAttribute("afs-string", cfg);
ptr->updateStat(true);
- EXPECT_EQ(875392u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
- EXPECT_EQ(609588u + sizeof_large_string_entry, ptr->getStatus().getUsed());
+ EXPECT_EQ(849992u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
+ EXPECT_EQ(584148u + sizeof_large_string_entry, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testArray<StringAttribute, string>(ptr, values);
}
@@ -2334,6 +2334,10 @@ AttributeTest::test_paged_attribute(const vespalib::string& name, const vespalib
size_t rounded_size = vespalib::round_up_to_page_size(1);
size_t lid_mapping_size = 1200;
size_t sv_maxlid = 1200;
+ if (rounded_size == 16_Ki) {
+ lid_mapping_size = 4200;
+ sv_maxlid = 1300;
+ }
if (rounded_size == 64_Ki) {
lid_mapping_size = 17000;
sv_maxlid = 1500;
diff --git a/searchlib/src/tests/attribute/extendattributes/extendattribute.cpp b/searchlib/src/tests/attribute/extendattributes/extendattribute.cpp
index 8f056323733..3f775e99891 100644
--- a/searchlib/src/tests/attribute/extendattributes/extendattribute.cpp
+++ b/searchlib/src/tests/attribute/extendattributes/extendattribute.cpp
@@ -1,9 +1,25 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/gtest/gtest.h>
+#include <vespa/eval/eval/fast_value.h>
+#include <vespa/eval/eval/tensor_spec.h>
+#include <vespa/eval/eval/value.h>
+#include <vespa/eval/eval/value_codec.h>
+#include <vespa/searchcommon/attribute/config.h>
#include <vespa/searchlib/attribute/extendableattributes.h>
#include <vespa/searchlib/attribute/single_raw_ext_attribute.h>
+#include <vespa/searchlib/tensor/tensor_ext_attribute.h>
+#include <vespa/searchlib/tensor/vector_bundle.h>
+#include <vespa/vespalib/stllike/asciistream.h>
+using search::attribute::Config;
+using search::attribute::BasicType;
+using search::attribute::CollectionType;
using search::attribute::SingleRawExtAttribute;
+using search::tensor::TensorExtAttribute;
+using vespalib::eval::FastValueBuilderFactory;
+using vespalib::eval::TensorSpec;
+using vespalib::eval::Value;
+using vespalib::eval::ValueType;
namespace search {
@@ -15,8 +31,46 @@ std::vector<char> as_vector(vespalib::ConstArrayRef<char> value) {
return {value.data(), value.data() + value.size()};
}
+std::vector<double> as_vector(vespalib::ConstArrayRef<double> value) {
+ return {value.data(), value.data() + value.size()};
+}
+
+vespalib::string vec_2d_spec("tensor(x[2])");
+vespalib::string vec_mixed_2d_spec("tensor(a{},x[2])");
+
+TensorSpec
+vec_2d(double x0, double x1)
+{
+ return TensorSpec(vec_2d_spec).add({{"x", 0}}, x0).add({{"x", 1}}, x1);
+}
+
+TensorSpec
+vec_mixed_2d(std::vector<std::vector<double>> val)
+{
+ TensorSpec spec(vec_mixed_2d_spec);
+ for (uint32_t a = 0; a < val.size(); ++a) {
+ vespalib::asciistream a_stream;
+ a_stream << a;
+ vespalib::string a_as_string = a_stream.str();
+ for (uint32_t x = 0; x < val[a].size(); ++x) {
+ spec.add({{"a", a_as_string.c_str()},{"x", x}}, val[a][x]);
+ }
+ }
+ return spec;
+}
+
+void add_doc(AttributeVector& attr, uint32_t exp_docid)
+{
+ uint32_t docid(0);
+ EXPECT_EQ(exp_docid, attr.getNumDocs());
+ attr.addDoc(docid);
+ EXPECT_EQ(exp_docid, docid);
+ EXPECT_EQ(exp_docid + 1, attr.getNumDocs());
+}
+
class ExtendAttributeTest : public ::testing::Test
{
+ std::vector<std::unique_ptr<Value>> _tensors;
protected:
ExtendAttributeTest() = default;
~ExtendAttributeTest() override = default;
@@ -27,16 +81,22 @@ protected:
template <typename Attribute>
void testExtendString(Attribute & attr);
void testExtendRaw(AttributeVector& attr);
+ void testExtendTensor(AttributeVector& attr);
+ const Value& create_tensor(const TensorSpec &spec);
};
+const Value&
+ExtendAttributeTest::create_tensor(const TensorSpec &spec)
+{
+ auto value = value_from_spec(spec, FastValueBuilderFactory::get());
+ _tensors.emplace_back(std::move(value));
+ return *_tensors.back();
+}
+
template <typename Attribute>
void ExtendAttributeTest::testExtendInteger(Attribute & attr)
{
- uint32_t docId(0);
- EXPECT_EQ(attr.getNumDocs(), 0u);
- attr.addDoc(docId);
- EXPECT_EQ(docId, 0u);
- EXPECT_EQ(attr.getNumDocs(), 1u);
+ add_doc(attr, 0);
attr.add(1, 10);
EXPECT_EQ(attr.getInt(0), 1);
attr.add(2, 20);
@@ -51,9 +111,7 @@ void ExtendAttributeTest::testExtendInteger(Attribute & attr)
EXPECT_EQ(v[1].getWeight(), 20);
}
}
- attr.addDoc(docId);
- EXPECT_EQ(docId, 1u);
- EXPECT_EQ(attr.getNumDocs(), 2u);
+ add_doc(attr, 1);
attr.add(3, 30);
EXPECT_EQ(attr.getInt(1), 3);
if (attr.hasMultiValue()) {
@@ -69,11 +127,7 @@ void ExtendAttributeTest::testExtendInteger(Attribute & attr)
template <typename Attribute>
void ExtendAttributeTest::testExtendFloat(Attribute & attr)
{
- uint32_t docId(0);
- EXPECT_EQ(attr.getNumDocs(), 0u);
- attr.addDoc(docId);
- EXPECT_EQ(docId, 0u);
- EXPECT_EQ(attr.getNumDocs(), 1u);
+ add_doc(attr, 0);
attr.add(1.7, 10);
EXPECT_EQ(attr.getInt(0), 1);
EXPECT_EQ(attr.getFloat(0), 1.7);
@@ -89,9 +143,7 @@ void ExtendAttributeTest::testExtendFloat(Attribute & attr)
EXPECT_EQ(v[1].getWeight(), 20);
}
}
- attr.addDoc(docId);
- EXPECT_EQ(docId, 1u);
- EXPECT_EQ(attr.getNumDocs(), 2u);
+ add_doc(attr, 1);
attr.add(3.6, 30);
EXPECT_EQ(attr.getFloat(1), 3.6);
if (attr.hasMultiValue()) {
@@ -107,11 +159,7 @@ void ExtendAttributeTest::testExtendFloat(Attribute & attr)
template <typename Attribute>
void ExtendAttributeTest::testExtendString(Attribute & attr)
{
- uint32_t docId(0);
- EXPECT_EQ(attr.getNumDocs(), 0u);
- attr.addDoc(docId);
- EXPECT_EQ(docId, 0u);
- EXPECT_EQ(attr.getNumDocs(), 1u);
+ add_doc(attr, 0);
attr.add("1.7", 10);
auto buf = attr.get_raw(0);
EXPECT_EQ(std::string(buf.data(), buf.size()), "1.7");
@@ -128,9 +176,7 @@ void ExtendAttributeTest::testExtendString(Attribute & attr)
EXPECT_EQ(v[1].getWeight(), 20);
}
}
- attr.addDoc(docId);
- EXPECT_EQ(docId, 1u);
- EXPECT_EQ(attr.getNumDocs(), 2u);
+ add_doc(attr, 1);
attr.add("3.6", 30);
buf = attr.get_raw(1);
EXPECT_EQ(std::string(buf.data(), buf.size()), "3.6");
@@ -150,41 +196,77 @@ void ExtendAttributeTest::testExtendRaw(AttributeVector& attr)
std::vector<char> zeros{10, 0, 0, 11};
auto* ext_attr = attr.getExtendInterface();
EXPECT_NE(nullptr, ext_attr);
- uint32_t docId(0);
- EXPECT_EQ(0u, attr.getNumDocs());
- attr.addDoc(docId);
- EXPECT_EQ(0u, docId);
- EXPECT_EQ(1u, attr.getNumDocs());
+ add_doc(attr, 0);
ext_attr->add(as_vector("1.7"));
auto buf = attr.get_raw(0);
EXPECT_EQ(as_vector("1.7"), as_vector(buf));
ext_attr->add(vespalib::ConstArrayRef<char>(as_vector("2.3")));
buf = attr.get_raw(0);
EXPECT_EQ(as_vector("2.3"), as_vector(buf));
- attr.addDoc(docId);
- EXPECT_EQ(1u, docId);
- EXPECT_EQ(attr.getNumDocs(), 2u);
+ add_doc(attr, 1);
ext_attr->add(as_vector("3.6"));
buf = attr.get_raw(1);
EXPECT_EQ(as_vector("3.6"), as_vector(buf));
buf = attr.get_raw(0);
EXPECT_EQ(as_vector("2.3"), as_vector(buf));
- attr.addDoc(docId);
- EXPECT_EQ(2u, docId);
+ add_doc(attr, 2);
ext_attr->add(zeros);
buf = attr.get_raw(2);
EXPECT_EQ(zeros, as_vector(buf));
- attr.addDoc(docId);
- EXPECT_EQ(3u, docId);
+ add_doc(attr, 3);
buf = attr.get_raw(3);
EXPECT_EQ(empty, as_vector(buf));
- attr.addDoc(docId);
- EXPECT_EQ(4u, docId);
+ add_doc(attr, 4);
ext_attr->add(empty);
buf = attr.get_raw(4);
EXPECT_EQ(empty, as_vector(buf));
}
+void ExtendAttributeTest::testExtendTensor(AttributeVector& attr)
+{
+ std::vector<double> empty_cells{0.0, 0.0};
+ std::vector<double> spec0_dense_cells{1.0, 2.0};
+ std::vector<double> spec0_mixed_cells0{3.0, 4.0};
+ std::vector<double> spec0_mixed_cells1{5.0, 6.0};
+ bool dense = attr.getConfig().tensorType().is_dense();
+ auto* ext_attr = attr.getExtendInterface();
+ EXPECT_NE(nullptr, ext_attr);
+ auto* tensor_attr = attr.asTensorAttribute();
+ EXPECT_NE(nullptr, tensor_attr);
+ add_doc(attr, 0);
+ TensorSpec spec0 = dense ? vec_2d(1.0, 2.0) : vec_mixed_2d({{3.0, 4.0}, {5.0, 6.0}});
+ EXPECT_TRUE(ext_attr->add(create_tensor(spec0)));
+ auto tensor = tensor_attr->getTensor(0);
+ EXPECT_NE(nullptr, tensor.get());
+ EXPECT_EQ(spec0, TensorSpec::from_value(*tensor));
+ EXPECT_EQ(dense, tensor_attr->supports_extract_cells_ref());
+ if (dense) {
+ EXPECT_EQ(spec0_dense_cells, as_vector(tensor_attr->extract_cells_ref(0).typify<double>()));
+ }
+ EXPECT_TRUE(tensor_attr->supports_get_tensor_ref());
+ EXPECT_EQ(spec0, TensorSpec::from_value(tensor_attr->get_tensor_ref(0)));
+ EXPECT_FALSE(tensor_attr->supports_get_serialized_tensor_ref());
+ auto vectors = tensor_attr->get_vectors(0);
+ if (dense) {
+ EXPECT_EQ(1, vectors.subspaces());
+ EXPECT_EQ(spec0_dense_cells, as_vector(vectors.cells(0).typify<double>()));
+ EXPECT_EQ(spec0_dense_cells, as_vector(tensor_attr->get_vector(0, 0).typify<double>()));
+ EXPECT_EQ(empty_cells, as_vector(tensor_attr->get_vector(0, 1).typify<double>()));
+ } else {
+ EXPECT_EQ(2, vectors.subspaces());
+ EXPECT_EQ(spec0_mixed_cells0, as_vector(vectors.cells(0).typify<double>()));
+ EXPECT_EQ(spec0_mixed_cells1, as_vector(vectors.cells(1).typify<double>()));
+ EXPECT_EQ(spec0_mixed_cells0, as_vector(tensor_attr->get_vector(0, 0).typify<double>()));
+ EXPECT_EQ(spec0_mixed_cells1, as_vector(tensor_attr->get_vector(0, 1).typify<double>()));
+ EXPECT_EQ(empty_cells, as_vector(tensor_attr->get_vector(0, 2).typify<double>()));
+ }
+ add_doc(attr, 1);
+ vectors = tensor_attr->get_vectors(1);
+ EXPECT_EQ(0, vectors.subspaces());
+ EXPECT_EQ(empty_cells, as_vector(tensor_attr->get_vector(1, 0).typify<double>()));
+ EXPECT_EQ(nullptr, tensor_attr->getTensor(1).get());
+}
+
TEST_F(ExtendAttributeTest, single_integer_ext_attribute)
{
SingleIntegerExtAttribute siattr("si1");
@@ -255,6 +337,24 @@ TEST_F(ExtendAttributeTest, single_raw_ext_attribute)
testExtendRaw(srattr);
}
+TEST_F(ExtendAttributeTest, tensor_ext_attribute_dense)
+{
+ Config cfg(BasicType::TENSOR, CollectionType::SINGLE);
+ cfg.setTensorType(ValueType::from_spec(vec_2d_spec));
+ TensorExtAttribute tattr("td1", cfg);
+ EXPECT_TRUE(! tattr.hasMultiValue());
+ testExtendTensor(tattr);
+}
+
+TEST_F(ExtendAttributeTest, tensor_ext_attribute_mixed)
+{
+ Config cfg(BasicType::TENSOR, CollectionType::SINGLE);
+ cfg.setTensorType(ValueType::from_spec(vec_mixed_2d_spec));
+ TensorExtAttribute tattr("tm1", cfg);
+ EXPECT_TRUE(! tattr.hasMultiValue());
+ testExtendTensor(tattr);
+}
+
}
GTEST_MAIN_RUN_ALL_TESTS()
diff --git a/searchlib/src/tests/attribute/multi_value_mapping/multi_value_mapping_test.cpp b/searchlib/src/tests/attribute/multi_value_mapping/multi_value_mapping_test.cpp
index df2a5ea2ac9..17e852c8b92 100644
--- a/searchlib/src/tests/attribute/multi_value_mapping/multi_value_mapping_test.cpp
+++ b/searchlib/src/tests/attribute/multi_value_mapping/multi_value_mapping_test.cpp
@@ -22,11 +22,11 @@ using vespalib::datastore::CompactionStrategy;
using vespalib::alloc::test::MemoryAllocatorObserver;
using AllocStats = MemoryAllocatorObserver::Stats;
-template <typename EntryT>
+template <typename ElemT>
void
-assertArray(const std::vector<EntryT> &exp, vespalib::ConstArrayRef<EntryT> values)
+assertArray(const std::vector<ElemT> &exp, vespalib::ConstArrayRef<ElemT> values)
{
- EXPECT_EQ(exp, std::vector<EntryT>(values.cbegin(), values.cend()));
+ EXPECT_EQ(exp, std::vector<ElemT>(values.cbegin(), values.cend()));
}
template <class MvMapping>
@@ -69,10 +69,10 @@ public:
constexpr float ALLOC_GROW_FACTOR = 0.2;
-template <typename EntryT>
+template <typename ElemT>
class MappingTestBase : public ::testing::Test {
protected:
- using MvMapping = search::attribute::MultiValueMapping<EntryT>;
+ using MvMapping = search::attribute::MultiValueMapping<ElemT>;
using AttributeType = MyAttribute<MvMapping>;
AllocStats _stats;
std::unique_ptr<MvMapping> _mvMapping;
@@ -82,8 +82,8 @@ protected:
using generation_t = vespalib::GenerationHandler::generation_t;
public:
- using ArrayRef = vespalib::ArrayRef<EntryT>;
- using ConstArrayRef = vespalib::ConstArrayRef<EntryT>;
+ using ArrayRef = vespalib::ArrayRef<ElemT>;
+ using ConstArrayRef = vespalib::ConstArrayRef<ElemT>;
MappingTestBase()
: _stats(),
_mvMapping(),
@@ -99,9 +99,9 @@ public:
_attr = std::make_unique<AttributeType>(*_mvMapping);
_maxSmallArraySize = maxSmallArraySize;
}
- void setup(uint32_t maxSmallArraySize, size_t minArrays, size_t maxArrays, size_t numArraysForNewBuffer, bool enable_free_lists = true) {
+ void setup(uint32_t maxSmallArraySize, size_t min_entries, size_t max_entries, size_t num_entries_for_new_buffer, bool enable_free_lists = true) {
ArrayStoreConfig config(maxSmallArraySize,
- ArrayStoreConfig::AllocSpec(minArrays, maxArrays, numArraysForNewBuffer, ALLOC_GROW_FACTOR));
+ ArrayStoreConfig::AllocSpec(min_entries, max_entries, num_entries_for_new_buffer, ALLOC_GROW_FACTOR));
config.enable_free_lists(enable_free_lists);
_mvMapping = std::make_unique<MvMapping>(config, vespalib::GrowStrategy(), std::make_unique<MemoryAllocatorObserver>(_stats));
_attr = std::make_unique<AttributeType>(*_mvMapping);
@@ -109,12 +109,12 @@ public:
}
~MappingTestBase() { }
- void set(uint32_t docId, const std::vector<EntryT> &values) { _mvMapping->set(docId, values); }
+ void set(uint32_t docId, const std::vector<ElemT> &values) { _mvMapping->set(docId, values); }
ConstArrayRef get(uint32_t docId) { return _mvMapping->get(docId); }
ArrayRef get_writable(uint32_t docId) { return _mvMapping->get_writable(docId); }
- void assertGet(uint32_t docId, const std::vector<EntryT> &exp) {
+ void assertGet(uint32_t docId, const std::vector<ElemT> &exp) {
ConstArrayRef act = get(docId);
- EXPECT_EQ(exp, std::vector<EntryT>(act.cbegin(), act.cend()));
+ EXPECT_EQ(exp, std::vector<ElemT>(act.cbegin(), act.cend()));
}
void assign_generation(generation_t current_gen) { _mvMapping->assign_generation(current_gen); }
void reclaim_memory(generation_t oldest_used_gen) { _mvMapping->reclaim_memory(oldest_used_gen); }
diff --git a/searchlib/src/tests/memoryindex/field_index/field_index_test.cpp b/searchlib/src/tests/memoryindex/field_index/field_index_test.cpp
index b57a2f42ea7..69478c09a25 100644
--- a/searchlib/src/tests/memoryindex/field_index/field_index_test.cpp
+++ b/searchlib/src/tests/memoryindex/field_index/field_index_test.cpp
@@ -1032,14 +1032,14 @@ TEST_F(BasicInverterTest, require_that_inversion_is_working)
auto beforeStats = getFeatureStoreMemStats(_fic);
LOG(info,
- "Before feature compaction: allocElems=%zu, usedElems=%zu"
- ", deadElems=%zu, holdElems=%zu"
+ "Before feature compaction: alloc_entries=%zu, used_entries=%zu"
+ ", dead_entries=%zu, hold_entries=%zu"
", freeBuffers=%u, activeBuffers=%u"
", holdBuffers=%u",
- beforeStats._allocElems,
- beforeStats._usedElems,
- beforeStats._deadElems,
- beforeStats._holdElems,
+ beforeStats._alloc_entries,
+ beforeStats._used_entries,
+ beforeStats._dead_entries,
+ beforeStats._hold_entries,
beforeStats._freeBuffers,
beforeStats._activeBuffers,
beforeStats._holdBuffers);
@@ -1052,14 +1052,14 @@ TEST_F(BasicInverterTest, require_that_inversion_is_working)
myCommit(_fic, *_pushThreads);
auto duringStats = getFeatureStoreMemStats(_fic);
LOG(info,
- "During feature compaction: allocElems=%zu, usedElems=%zu"
- ", deadElems=%zu, holdElems=%zu"
+ "During feature compaction: alloc_entries=%zu, used_entries=%zu"
+ ", dead_entries=%zu, hold_entries=%zu"
", freeBuffers=%u, activeBuffers=%u"
", holdBuffers=%u",
- duringStats._allocElems,
- duringStats._usedElems,
- duringStats._deadElems,
- duringStats._holdElems,
+ duringStats._alloc_entries,
+ duringStats._used_entries,
+ duringStats._dead_entries,
+ duringStats._hold_entries,
duringStats._freeBuffers,
duringStats._activeBuffers,
duringStats._holdBuffers);
@@ -1067,14 +1067,14 @@ TEST_F(BasicInverterTest, require_that_inversion_is_working)
myCommit(_fic, *_pushThreads);
auto afterStats = getFeatureStoreMemStats(_fic);
LOG(info,
- "After feature compaction: allocElems=%zu, usedElems=%zu"
- ", deadElems=%zu, holdElems=%zu"
+ "After feature compaction: alloc_entries=%zu, used_entries=%zu"
+ ", dead_entries=%zu, hold_entries=%zu"
", freeBuffers=%u, activeBuffers=%u"
", holdBuffers=%u",
- afterStats._allocElems,
- afterStats._usedElems,
- afterStats._deadElems,
- afterStats._holdElems,
+ afterStats._alloc_entries,
+ afterStats._used_entries,
+ afterStats._dead_entries,
+ afterStats._hold_entries,
afterStats._freeBuffers,
afterStats._activeBuffers,
afterStats._holdBuffers);
diff --git a/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp b/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp
index 8073fb8d232..e3b9cf9702d 100644
--- a/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp
+++ b/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp
@@ -462,8 +462,8 @@ TEST(MemoryIndexTest, require_that_num_docs_and_doc_id_limit_is_returned)
TEST(MemoryIndexTest, require_that_we_understand_the_memory_footprint)
{
- constexpr size_t BASE_ALLOCATED = 361032u;
- constexpr size_t BASE_USED = 151188u;
+ constexpr size_t BASE_ALLOCATED = 360936u;
+ constexpr size_t BASE_USED = 150804u;
{
MySetup setup;
Index index(setup);
diff --git a/searchlib/src/tests/predicate/document_features_store_test.cpp b/searchlib/src/tests/predicate/document_features_store_test.cpp
index 4ac4bdc32f0..d30df9dba6e 100644
--- a/searchlib/src/tests/predicate/document_features_store_test.cpp
+++ b/searchlib/src/tests/predicate/document_features_store_test.cpp
@@ -165,17 +165,17 @@ TEST("require that both features and ranges are removed by 'remove'") {
TEST("require that both features and ranges counts towards memory usage") {
DocumentFeaturesStore features_store(10);
- EXPECT_EQUAL(50136u, features_store.getMemoryUsage().usedBytes());
+ EXPECT_EQUAL(50064u, features_store.getMemoryUsage().usedBytes());
PredicateTreeAnnotations annotations;
annotations.features.push_back(PredicateHash::hash64("foo=100-199"));
features_store.insert(annotations, doc_id);
- EXPECT_EQUAL(50144u, features_store.getMemoryUsage().usedBytes());
+ EXPECT_EQUAL(50072u, features_store.getMemoryUsage().usedBytes());
annotations.features.clear();
annotations.range_features.push_back({"foo", 100, 199});
features_store.insert(annotations, doc_id + 1);
- EXPECT_EQUAL(50240u, features_store.getMemoryUsage().usedBytes());
+ EXPECT_EQUAL(50168u, features_store.getMemoryUsage().usedBytes());
}
TEST("require that DocumentFeaturesStore can be serialized") {
@@ -205,17 +205,17 @@ TEST("require that serialization cleans up wordstore") {
PredicateTreeAnnotations annotations;
annotations.range_features.push_back({"foo", 100, 199});
features_store.insert(annotations, doc_id);
- EXPECT_EQUAL(50232u, features_store.getMemoryUsage().usedBytes());
+ EXPECT_EQUAL(50160u, features_store.getMemoryUsage().usedBytes());
annotations.range_features.push_back({"bar", 100, 199});
features_store.insert(annotations, doc_id + 1);
- EXPECT_EQUAL(50620u, features_store.getMemoryUsage().usedBytes());
+ EXPECT_EQUAL(50548u, features_store.getMemoryUsage().usedBytes());
features_store.remove(doc_id + 1);
- EXPECT_EQUAL(50572u, features_store.getMemoryUsage().usedBytes());
+ EXPECT_EQUAL(50500u, features_store.getMemoryUsage().usedBytes());
vespalib::DataBuffer buffer;
features_store.serialize(buffer);
DocumentFeaturesStore features_store2(buffer);
- EXPECT_EQUAL(50232u, features_store2.getMemoryUsage().usedBytes());
+ EXPECT_EQUAL(50160u, features_store2.getMemoryUsage().usedBytes());
}
diff --git a/searchlib/src/vespa/searchlib/attribute/attributevector.h b/searchlib/src/vespa/searchlib/attribute/attributevector.h
index 3d14622ca02..e40785911ea 100644
--- a/searchlib/src/vespa/searchlib/attribute/attributevector.h
+++ b/searchlib/src/vespa/searchlib/attribute/attributevector.h
@@ -38,6 +38,8 @@ namespace vespalib::alloc {
class Alloc;
}
+namespace vespalib::eval { struct Value; }
+
namespace search {
template <typename T> class ComponentGuard;
@@ -86,6 +88,7 @@ public:
virtual bool add(double, int32_t = 1) { return false; }
virtual bool add(const char *, int32_t = 1) { return false; }
virtual bool add(vespalib::ConstArrayRef<char>, int32_t = 1) { return false; }
+ virtual bool add(const vespalib::eval::Value&, int32_t = 1) { return false; }
virtual ~IExtendAttribute() = default;
};
diff --git a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h
index bd624e9f388..4fce64aa762 100644
--- a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h
+++ b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h
@@ -12,18 +12,18 @@ namespace search::attribute {
/**
* Class for mapping from document id to an array of values.
*/
-template <typename EntryT, typename RefT = vespalib::datastore::EntryRefT<19> >
+template <typename ElemT, typename RefT = vespalib::datastore::EntryRefT<19> >
class MultiValueMapping : public MultiValueMappingBase
{
public:
- using MultiValueType = EntryT;
+ using MultiValueType = ElemT;
using RefType = RefT;
- using ReadView = MultiValueMappingReadView<EntryT, RefT>;
+ using ReadView = MultiValueMappingReadView<ElemT, RefT>;
private:
- using ArrayRef = vespalib::ArrayRef<EntryT>;
- using ArrayStore = vespalib::datastore::ArrayStore<EntryT, RefT>;
+ using ArrayRef = vespalib::ArrayRef<ElemT>;
+ using ArrayStore = vespalib::datastore::ArrayStore<ElemT, RefT>;
using generation_t = vespalib::GenerationHandler::generation_t;
- using ConstArrayRef = vespalib::ConstArrayRef<EntryT>;
+ using ConstArrayRef = vespalib::ConstArrayRef<ElemT>;
ArrayStore _store;
public:
@@ -73,7 +73,7 @@ public:
static vespalib::datastore::ArrayStoreConfig optimizedConfigForHugePage(size_t maxSmallArraySize,
size_t hugePageSize,
size_t smallPageSize,
- size_t minNumArraysForNewBuffer,
+ size_t min_num_entries_for_new_buffer,
float allocGrowFactor,
bool enable_free_lists);
};
diff --git a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.hpp b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.hpp
index b486fa60265..ab68bea58cc 100644
--- a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.hpp
+++ b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.hpp
@@ -7,8 +7,8 @@
namespace search::attribute {
-template <typename EntryT, typename RefT>
-MultiValueMapping<EntryT,RefT>::MultiValueMapping(const vespalib::datastore::ArrayStoreConfig &storeCfg,
+template <typename ElemT, typename RefT>
+MultiValueMapping<ElemT,RefT>::MultiValueMapping(const vespalib::datastore::ArrayStoreConfig &storeCfg,
const vespalib::GrowStrategy &gs,
std::shared_ptr<vespalib::alloc::MemoryAllocator> memory_allocator)
: MultiValueMappingBase(gs, ArrayStore::getGenerationHolderLocation(_store), memory_allocator),
@@ -16,12 +16,12 @@ MultiValueMapping<EntryT,RefT>::MultiValueMapping(const vespalib::datastore::Arr
{
}
-template <typename EntryT, typename RefT>
-MultiValueMapping<EntryT,RefT>::~MultiValueMapping() = default;
+template <typename ElemT, typename RefT>
+MultiValueMapping<ElemT,RefT>::~MultiValueMapping() = default;
-template <typename EntryT, typename RefT>
+template <typename ElemT, typename RefT>
void
-MultiValueMapping<EntryT,RefT>::set(uint32_t docId, ConstArrayRef values)
+MultiValueMapping<ElemT,RefT>::set(uint32_t docId, ConstArrayRef values)
{
_indices.ensure_size(docId + 1);
EntryRef oldRef(_indices[docId].load_relaxed());
@@ -31,18 +31,18 @@ MultiValueMapping<EntryT,RefT>::set(uint32_t docId, ConstArrayRef values)
_store.remove(oldRef);
}
-template <typename EntryT, typename RefT>
+template <typename ElemT, typename RefT>
vespalib::MemoryUsage
-MultiValueMapping<EntryT,RefT>::update_stat(const CompactionStrategy& compaction_strategy)
+MultiValueMapping<ElemT,RefT>::update_stat(const CompactionStrategy& compaction_strategy)
{
auto retval = _store.update_stat(compaction_strategy);
retval.merge(_indices.getMemoryUsage());
return retval;
}
-template <typename EntryT, typename RefT>
+template <typename ElemT, typename RefT>
void
-MultiValueMapping<EntryT,RefT>::compact_worst(const CompactionStrategy& compaction_strategy)
+MultiValueMapping<ElemT,RefT>::compact_worst(const CompactionStrategy& compaction_strategy)
{
vespalib::datastore::ICompactionContext::UP compactionContext(_store.compact_worst(compaction_strategy));
if (compactionContext) {
@@ -50,29 +50,29 @@ MultiValueMapping<EntryT,RefT>::compact_worst(const CompactionStrategy& compacti
}
}
-template <typename EntryT, typename RefT>
+template <typename ElemT, typename RefT>
vespalib::MemoryUsage
-MultiValueMapping<EntryT,RefT>::getArrayStoreMemoryUsage() const
+MultiValueMapping<ElemT,RefT>::getArrayStoreMemoryUsage() const
{
return _store.getMemoryUsage();
}
-template <typename EntryT, typename RefT>
+template <typename ElemT, typename RefT>
vespalib::AddressSpace
-MultiValueMapping<EntryT, RefT>::getAddressSpaceUsage() const {
+MultiValueMapping<ElemT, RefT>::getAddressSpaceUsage() const {
return _store.addressSpaceUsage();
}
-template <typename EntryT, typename RefT>
+template <typename ElemT, typename RefT>
vespalib::datastore::ArrayStoreConfig
-MultiValueMapping<EntryT, RefT>::optimizedConfigForHugePage(size_t maxSmallArraySize,
+MultiValueMapping<ElemT, RefT>::optimizedConfigForHugePage(size_t maxSmallArraySize,
size_t hugePageSize,
size_t smallPageSize,
- size_t minNumArraysForNewBuffer,
+ size_t min_num_entries_for_new_buffer,
float allocGrowFactor,
bool enable_free_lists)
{
- auto result = ArrayStore::optimizedConfigForHugePage(maxSmallArraySize, hugePageSize, smallPageSize, minNumArraysForNewBuffer, allocGrowFactor);
+ auto result = ArrayStore::optimizedConfigForHugePage(maxSmallArraySize, hugePageSize, smallPageSize, min_num_entries_for_new_buffer, allocGrowFactor);
result.enable_free_lists(enable_free_lists);
return result;
}
diff --git a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping_read_view.h b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping_read_view.h
index 116e069e8b4..41138ff0890 100644
--- a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping_read_view.h
+++ b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping_read_view.h
@@ -11,12 +11,12 @@ namespace search::attribute {
/**
* Class for mapping from document id to an array of values as reader.
*/
-template <typename EntryT, typename RefT = vespalib::datastore::EntryRefT<19> >
+template <typename ElemT, typename RefT = vespalib::datastore::EntryRefT<19> >
class MultiValueMappingReadView
{
using AtomicEntryRef = vespalib::datastore::AtomicEntryRef;
using Indices = vespalib::ConstArrayRef<AtomicEntryRef>;
- using ArrayStore = vespalib::datastore::ArrayStore<EntryT, RefT>;
+ using ArrayStore = vespalib::datastore::ArrayStore<ElemT, RefT>;
Indices _indices;
const ArrayStore* _store;
@@ -31,7 +31,7 @@ public:
_store(store)
{
}
- vespalib::ConstArrayRef<EntryT> get(uint32_t doc_id) const { return _store->get(_indices[doc_id].load_acquire()); }
+ vespalib::ConstArrayRef<ElemT> get(uint32_t doc_id) const { return _store->get(_indices[doc_id].load_acquire()); }
bool valid() const noexcept { return _store != nullptr; }
};
diff --git a/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp b/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp
index ea449300aef..1009fa2fb5f 100644
--- a/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp
+++ b/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp
@@ -51,7 +51,7 @@ template <typename B, typename M>
MultiValueNumericPostingAttribute<B, M>::~MultiValueNumericPostingAttribute()
{
this->disableFreeLists();
- this->disableElemHoldList();
+ this->disable_entry_hold_list();
clearAllPostings();
}
diff --git a/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp b/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp
index cd46bbb5a8a..19840b5a474 100644
--- a/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp
+++ b/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp
@@ -27,7 +27,7 @@ template <typename B, typename T>
MultiValueStringPostingAttributeT<B, T>::~MultiValueStringPostingAttributeT()
{
this->disableFreeLists();
- this->disableElemHoldList();
+ this->disable_entry_hold_list();
clearAllPostings();
}
diff --git a/searchlib/src/vespa/searchlib/attribute/postinglistattribute.h b/searchlib/src/vespa/searchlib/attribute/postinglistattribute.h
index 29440b6ce43..ecf7a46f21e 100644
--- a/searchlib/src/vespa/searchlib/attribute/postinglistattribute.h
+++ b/searchlib/src/vespa/searchlib/attribute/postinglistattribute.h
@@ -58,7 +58,7 @@ protected:
void updatePostings(PostingMap &changePost, const vespalib::datastore::EntryComparator &cmp);
void clearAllPostings();
void disableFreeLists() { _postingList.disableFreeLists(); }
- void disableElemHoldList() { _postingList.disableElemHoldList(); }
+ void disable_entry_hold_list() { _postingList.disable_entry_hold_list(); }
void handle_load_posting_lists_and_update_enum_store(enumstore::EnumeratedPostingsLoader& loader);
bool forwardedOnAddDoc(DocId doc, size_t wantSize, size_t wantCapacity);
diff --git a/searchlib/src/vespa/searchlib/attribute/postingstore.cpp b/searchlib/src/vespa/searchlib/attribute/postingstore.cpp
index 94720212faf..2703201b292 100644
--- a/searchlib/src/vespa/searchlib/attribute/postingstore.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/postingstore.cpp
@@ -231,7 +231,7 @@ PostingStore<DataT>::dropBitVector(EntryRef &ref)
(void) tree;
(void) docFreq;
_bvs.erase(ref.ref());
- _store.holdElem(iRef, 1);
+ _store.hold_entry(iRef);
_status.decBitVectors();
_bvExtraBytes -= bv->writer().extraByteSize();
ref = ref2;
@@ -267,7 +267,7 @@ PostingStore<DataT>::makeBitVector(EntryRef &ref)
if (_enableOnlyBitVector) {
BTreeType *tree = getWTreeEntry(iRef);
tree->clear(_allocator);
- _store.holdElem(ref, 1);
+ _store.hold_entry(ref);
} else {
bve->_tree = ref;
}
@@ -590,19 +590,19 @@ PostingStore<DataT>::clear(const EntryRef ref)
assert(isBTree(iRef2));
BTreeType *tree = getWTreeEntry(iRef2);
tree->clear(_allocator);
- _store.holdElem(iRef2, 1);
+ _store.hold_entry(iRef2);
}
_bvs.erase(ref.ref());
_status.decBitVectors();
_bvExtraBytes -= bve->_bv->writer().extraByteSize();
- _store.holdElem(ref, 1);
+ _store.hold_entry(ref);
} else {
BTreeType *tree = getWTreeEntry(iRef);
tree->clear(_allocator);
- _store.holdElem(ref, 1);
+ _store.hold_entry(ref);
}
} else {
- _store.holdElem(ref, clusterSize);
+ _store.hold_entry(ref);
}
}
diff --git a/searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp b/searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp
index 1775774171d..de4a7157dae 100644
--- a/searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp
+++ b/searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp
@@ -13,7 +13,7 @@ template <typename B>
SingleValueNumericPostingAttribute<B>::~SingleValueNumericPostingAttribute()
{
this->disableFreeLists();
- this->disableElemHoldList();
+ this->disable_entry_hold_list();
clearAllPostings();
}
diff --git a/searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp b/searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp
index eef72984e79..1ec9b54a73b 100644
--- a/searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp
+++ b/searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp
@@ -27,7 +27,7 @@ template <typename B>
SingleValueStringPostingAttributeT<B>::~SingleValueStringPostingAttributeT()
{
this->disableFreeLists();
- this->disableElemHoldList();
+ this->disable_entry_hold_list();
clearAllPostings();
}
diff --git a/searchlib/src/vespa/searchlib/memoryindex/feature_store.cpp b/searchlib/src/vespa/searchlib/memoryindex/feature_store.cpp
index 72f4a7ae579..4bc7f5b1144 100644
--- a/searchlib/src/vespa/searchlib/memoryindex/feature_store.cpp
+++ b/searchlib/src/vespa/searchlib/memoryindex/feature_store.cpp
@@ -36,7 +36,7 @@ EntryRef
FeatureStore::addFeatures(const uint8_t *src, uint64_t byteLen)
{
uint32_t pad = Aligner::pad(byteLen);
- auto result = _store.rawAllocator<uint8_t>(_typeId).alloc(byteLen + pad, DECODE_SAFETY);
+ auto result = _store.rawAllocator<uint8_t>(_typeId).alloc((byteLen + pad) / buffer_array_size, DECODE_SAFETY_ENTRIES);
uint8_t *dst = result.data;
memcpy(dst, src, byteLen);
dst += byteLen;
@@ -113,7 +113,7 @@ FeatureStore::add_features_guard_bytes()
{
uint32_t len = DECODE_SAFETY;
uint32_t pad = Aligner::pad(len);
- auto result = _store.rawAllocator<uint8_t>(_typeId).alloc(len + pad);
+ auto result = _store.rawAllocator<uint8_t>(_typeId).alloc((len + pad) / buffer_array_size);
memset(result.data, 0, len + pad);
}
diff --git a/searchlib/src/vespa/searchlib/memoryindex/feature_store.h b/searchlib/src/vespa/searchlib/memoryindex/feature_store.h
index 53588fa2894..1e48189987e 100644
--- a/searchlib/src/vespa/searchlib/memoryindex/feature_store.h
+++ b/searchlib/src/vespa/searchlib/memoryindex/feature_store.h
@@ -29,6 +29,7 @@ private:
using PosOccFieldsParams = bitcompression::PosOccFieldsParams;
static constexpr uint32_t DECODE_SAFETY = 16;
+ static constexpr uint32_t DECODE_SAFETY_ENTRIES = 16 / buffer_array_size;
DataStoreType _store;
@@ -117,7 +118,7 @@ public:
* overrun beyond the compressed data either goes into other features
* already written or into the guard area.
*
- * If buffer type is changed to have a nonzero numArraysForNewBuffer then
+ * If buffer type is changed to have a nonzero num_entries_for_new_buffer then
* extra logic to add guard bytes is needed when switching primary buffer
* to avoid issues if the buffer is resumed as primary buffer later on.
*/
diff --git a/searchlib/src/vespa/searchlib/memoryindex/field_index.cpp b/searchlib/src/vespa/searchlib/memoryindex/field_index.cpp
index 4be3031303e..8dd76a90b14 100644
--- a/searchlib/src/vespa/searchlib/memoryindex/field_index.cpp
+++ b/searchlib/src/vespa/searchlib/memoryindex/field_index.cpp
@@ -55,9 +55,9 @@ template <bool interleaved_features>
FieldIndex<interleaved_features>::~FieldIndex()
{
_postingListStore.disableFreeLists();
- _postingListStore.disableElemHoldList();
+ _postingListStore.disable_entry_hold_list();
_dict.disableFreeLists();
- _dict.disableElemHoldList();
+ _dict.disable_entry_hold_list();
// XXX: Kludge
for (DictionaryTree::Iterator it = _dict.begin();
it.valid(); ++it) {
diff --git a/searchlib/src/vespa/searchlib/memoryindex/word_store.cpp b/searchlib/src/vespa/searchlib/memoryindex/word_store.cpp
index 3e4c38ceb0e..e330dc83055 100644
--- a/searchlib/src/vespa/searchlib/memoryindex/word_store.cpp
+++ b/searchlib/src/vespa/searchlib/memoryindex/word_store.cpp
@@ -27,7 +27,7 @@ WordStore::addWord(const vespalib::stringref word)
{
size_t wordSize = word.size() + 1;
size_t bufferSize = wordSize + Aligner::pad(wordSize);
- auto result = _store.rawAllocator<char>(_typeId).alloc(bufferSize);
+ auto result = _store.rawAllocator<char>(_typeId).alloc(bufferSize / buffer_array_size);
char *be = result.data;
for (size_t i = 0; i < word.size(); ++i) {
*be++ = word[i];
diff --git a/searchlib/src/vespa/searchlib/predicate/document_features_store.cpp b/searchlib/src/vespa/searchlib/predicate/document_features_store.cpp
index 604a467a6e6..a6a82ec09f8 100644
--- a/searchlib/src/vespa/searchlib/predicate/document_features_store.cpp
+++ b/searchlib/src/vespa/searchlib/predicate/document_features_store.cpp
@@ -102,7 +102,7 @@ DocumentFeaturesStore::DocumentFeaturesStore(DataBuffer &buffer)
DocumentFeaturesStore::~DocumentFeaturesStore() {
_word_index.disableFreeLists();
- _word_index.disableElemHoldList();
+ _word_index.disable_entry_hold_list();
_word_index.getAllocator().freeze();
_word_index.clear();
}
diff --git a/searchlib/src/vespa/searchlib/predicate/predicate_interval_store.cpp b/searchlib/src/vespa/searchlib/predicate/predicate_interval_store.cpp
index af809b2fa69..af5aae6e519 100644
--- a/searchlib/src/vespa/searchlib/predicate/predicate_interval_store.cpp
+++ b/searchlib/src/vespa/searchlib/predicate/predicate_interval_store.cpp
@@ -95,7 +95,7 @@ PredicateIntervalStore::remove(EntryRef ref) {
// BufferState &state = _store.getBufferState(buffer_id);
// uint32_t type_id = state.getTypeId();
// uint32_t size = type_id <= MAX_ARRAY_SIZE ? type_id : 1;
- // _store.holdElem(ref, size);
+ // _store.hold_entries(ref, size);
}
}
diff --git a/searchlib/src/vespa/searchlib/predicate/simple_index.hpp b/searchlib/src/vespa/searchlib/predicate/simple_index.hpp
index c6f640d72ed..9320488f88e 100644
--- a/searchlib/src/vespa/searchlib/predicate/simple_index.hpp
+++ b/searchlib/src/vespa/searchlib/predicate/simple_index.hpp
@@ -41,7 +41,7 @@ SimpleIndex<Posting, Key, DocId>::insertIntoVectorPosting(vespalib::datastore::E
template <typename Posting, typename Key, typename DocId>
SimpleIndex<Posting, Key, DocId>::~SimpleIndex() {
_btree_posting_lists.disableFreeLists();
- _btree_posting_lists.disableElemHoldList();
+ _btree_posting_lists.disable_entry_hold_list();
for (auto it = _dictionary.begin(); it.valid(); ++it) {
vespalib::datastore::EntryRef ref(it.getData());
@@ -51,13 +51,13 @@ SimpleIndex<Posting, Key, DocId>::~SimpleIndex() {
}
_vector_posting_lists.disableFreeLists();
- _vector_posting_lists.disableElemHoldList();
+ _vector_posting_lists.disable_entry_hold_list();
_vector_posting_lists.clear();
_vector_posting_lists.getAllocator().freeze();
_vector_posting_lists.getAllocator().reclaim_all_memory();
_dictionary.disableFreeLists();
- _dictionary.disableElemHoldList();
+ _dictionary.disable_entry_hold_list();
_dictionary.clear();
_dictionary.getAllocator().freeze();
_dictionary.getAllocator().reclaim_all_memory();
diff --git a/searchlib/src/vespa/searchlib/tensor/CMakeLists.txt b/searchlib/src/vespa/searchlib/tensor/CMakeLists.txt
index c8c5d4d4257..313863d8dcb 100644
--- a/searchlib/src/vespa/searchlib/tensor/CMakeLists.txt
+++ b/searchlib/src/vespa/searchlib/tensor/CMakeLists.txt
@@ -40,6 +40,7 @@ vespa_add_library(searchlib_tensor OBJECT
tensor_buffer_store.cpp
tensor_buffer_type_mapper.cpp
tensor_deserialize.cpp
+ tensor_ext_attribute.cpp
tensor_store.cpp
DEPENDS
)
diff --git a/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp b/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp
index c373f6bdcd0..c51d0ec7fd3 100644
--- a/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp
@@ -62,10 +62,10 @@ DenseTensorStore::BufferType::BufferType(const TensorSizeCalc &tensorSizeCalc, s
DenseTensorStore::BufferType::~BufferType() = default;
void
-DenseTensorStore::BufferType::cleanHold(void *buffer, size_t offset,
- ElemCount numElems, CleanContext)
+DenseTensorStore::BufferType::clean_hold(void *buffer, size_t offset, EntryCount num_entries, CleanContext)
{
- memset(static_cast<char *>(buffer) + offset, 0, numElems);
+ auto num_elems = num_entries * getArraySize();
+ memset(static_cast<char *>(buffer) + offset * getArraySize(), 0, num_elems);
}
const vespalib::alloc::MemoryAllocator*
@@ -107,7 +107,7 @@ DenseTensorStore::allocRawBuffer()
{
size_t bufSize = getBufSize();
size_t alignedBufSize = _tensorSizeCalc.alignedSize();
- auto result = _concreteStore.freeListRawAllocator<char>(0u).alloc(alignedBufSize);
+ auto result = _concreteStore.freeListRawAllocator<char>(0u).alloc(1);
clearPadAreaAfterBuffer(result.data, bufSize, alignedBufSize);
return result;
}
@@ -118,7 +118,7 @@ DenseTensorStore::holdTensor(EntryRef ref)
if (!ref.valid()) {
return;
}
- _concreteStore.holdElem(ref, _tensorSizeCalc.alignedSize());
+ _concreteStore.hold_entry(ref);
}
TensorStore::EntryRef
diff --git a/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h b/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h
index 9e326e0ab1e..0dd483e7f08 100644
--- a/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h
+++ b/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h
@@ -44,7 +44,7 @@ public:
public:
BufferType(const TensorSizeCalc &tensorSizeCalc, std::shared_ptr<vespalib::alloc::MemoryAllocator> allocator);
~BufferType() override;
- void cleanHold(void *buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx) override;
+ void clean_hold(void *buffer, size_t offset, EntryCount num_entries, CleanContext cleanCtx) override;
const vespalib::alloc::MemoryAllocator* get_memory_allocator() const override;
};
private:
diff --git a/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.cpp b/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.cpp
index fa13ab6303c..8526138fd31 100644
--- a/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.cpp
@@ -30,11 +30,11 @@ DirectTensorStore::TensorBufferType::TensorBufferType()
}
void
-DirectTensorStore::TensorBufferType::cleanHold(void* buffer, size_t offset, ElemCount num_elems, CleanContext clean_ctx)
+DirectTensorStore::TensorBufferType::clean_hold(void* buffer, size_t offset, EntryCount num_entries, CleanContext clean_ctx)
{
TensorSP* elem = static_cast<TensorSP*>(buffer) + offset;
const auto& empty = empty_entry();
- for (size_t i = 0; i < num_elems; ++i) {
+ for (size_t i = 0; i < num_entries; ++i) {
clean_ctx.extraBytesCleaned((*elem)->get_memory_usage().allocatedBytes());
*elem = empty;
++elem;
@@ -69,7 +69,7 @@ DirectTensorStore::holdTensor(EntryRef ref)
}
const auto& tensor = _tensor_store.getEntry(ref);
assert(tensor);
- _tensor_store.holdElem(ref, 1, tensor->get_memory_usage().allocatedBytes());
+ _tensor_store.hold_entry(ref, tensor->get_memory_usage().allocatedBytes());
}
EntryRef
diff --git a/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h b/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h
index 01084e89776..1230494fe41 100644
--- a/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h
+++ b/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h
@@ -20,7 +20,7 @@ namespace search::tensor {
*/
class DirectTensorStore : public TensorStore {
private:
- // Note: Must use SP (instead of UP) because of fallbackCopy() and initializeReservedElements() in BufferType,
+ // Note: Must use SP (instead of UP) because of fallback_copy() and initialize_reserved_entries() in BufferType,
// and implementation of move().
using TensorSP = std::shared_ptr<vespalib::eval::Value>;
using TensorStoreType = vespalib::datastore::DataStore<TensorSP>;
@@ -32,7 +32,7 @@ private:
using CleanContext = typename ParentType::CleanContext;
public:
TensorBufferType();
- void cleanHold(void* buffer, size_t offset, ElemCount num_elems, CleanContext clean_ctx) override;
+ void clean_hold(void* buffer, size_t offset, EntryCount num_entries, CleanContext clean_ctx) override;
};
TensorStoreType _tensor_store;
diff --git a/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.cpp b/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.cpp
index cb074348f08..5d3b2206703 100644
--- a/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.cpp
@@ -12,7 +12,7 @@ using vespalib::alloc::MemoryAllocator;
namespace search::tensor {
LargeSubspacesBufferType::LargeSubspacesBufferType(const AllocSpec& spec, std::shared_ptr<MemoryAllocator> memory_allocator, TensorBufferTypeMapper& type_mapper) noexcept
- : ParentType(1u, spec.minArraysInBuffer, spec.maxArraysInBuffer, spec.numArraysForNewBuffer, spec.allocGrowFactor),
+ : ParentType(1u, spec.min_entries_in_buffer, spec.max_entries_in_buffer, spec.num_entries_for_new_buffer, spec.allocGrowFactor),
_memory_allocator(std::move(memory_allocator)),
_ops(type_mapper.get_tensor_buffer_operations())
{
@@ -21,10 +21,10 @@ LargeSubspacesBufferType::LargeSubspacesBufferType(const AllocSpec& spec, std::s
LargeSubspacesBufferType::~LargeSubspacesBufferType() = default;
void
-LargeSubspacesBufferType::cleanHold(void* buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx)
+LargeSubspacesBufferType::clean_hold(void* buffer, size_t offset, EntryCount num_entries, CleanContext cleanCtx)
{
auto elem = static_cast<ArrayType*>(buffer) + offset;
- for (size_t i = 0; i < numElems; ++i) {
+ for (size_t i = 0; i < num_entries; ++i) {
if (!elem->empty()) {
cleanCtx.extraBytesCleaned(elem->size());
_ops.reclaim_labels({elem->data(), elem->size()});
@@ -35,10 +35,10 @@ LargeSubspacesBufferType::cleanHold(void* buffer, size_t offset, ElemCount numEl
}
void
-LargeSubspacesBufferType::destroyElements(void *buffer, ElemCount numElems)
+LargeSubspacesBufferType::destroy_entries(void *buffer, EntryCount num_entries)
{
auto elem = static_cast<ArrayType*>(buffer);
- for (size_t i = 0; i < numElems; ++i) {
+ for (size_t i = 0; i < num_entries; ++i) {
if (!elem->empty()) {
_ops.reclaim_labels({elem->data(), elem->size()});
ArrayType().swap(*elem);
@@ -48,11 +48,11 @@ LargeSubspacesBufferType::destroyElements(void *buffer, ElemCount numElems)
}
void
-LargeSubspacesBufferType::fallbackCopy(void *newBuffer, const void *oldBuffer, ElemCount numElems)
+LargeSubspacesBufferType::fallback_copy(void *newBuffer, const void *oldBuffer, EntryCount num_entries)
{
auto old_elems = static_cast<const ArrayType*>(oldBuffer);
auto new_elems = static_cast<ArrayType*>(newBuffer);
- for (size_t i = 0; i < numElems; ++i) {
+ for (size_t i = 0; i < num_entries; ++i) {
auto& old_elem = old_elems[i];
new (new_elems + i) ArrayType(old_elem);
if (!old_elem.empty()) {
@@ -62,12 +62,12 @@ LargeSubspacesBufferType::fallbackCopy(void *newBuffer, const void *oldBuffer, E
}
void
-LargeSubspacesBufferType::initializeReservedElements(void *buffer, ElemCount reservedElements)
+LargeSubspacesBufferType::initialize_reserved_entries(void *buffer, EntryCount reserved_entries)
{
- auto new_elems = static_cast<ArrayType*>(buffer);
+ auto new_entries = static_cast<ArrayType*>(buffer);
const auto& empty = empty_entry();
- for (size_t i = 0; i < reservedElements; ++i) {
- new (new_elems + i) ArrayType(empty);
+ for (size_t i = 0; i < reserved_entries; ++i) {
+ new (new_entries + i) ArrayType(empty);
}
}
diff --git a/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.h b/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.h
index cfab8ef20af..8cce08e9d81 100644
--- a/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.h
+++ b/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.h
@@ -30,10 +30,10 @@ class LargeSubspacesBufferType : public vespalib::datastore::BufferType<vespalib
public:
LargeSubspacesBufferType(const AllocSpec& spec, std::shared_ptr<vespalib::alloc::MemoryAllocator> memory_allocator, TensorBufferTypeMapper& type_mapper) noexcept;
~LargeSubspacesBufferType() override;
- void cleanHold(void* buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx) override;
- void destroyElements(void *buffer, ElemCount numElems) override;
- void fallbackCopy(void *newBuffer, const void *oldBuffer, ElemCount numElems) override;
- void initializeReservedElements(void *buffer, ElemCount reservedElements) override;
+ void clean_hold(void* buffer, size_t offset, EntryCount num_entries, CleanContext cleanCtx) override;
+ void destroy_entries(void *buffer, EntryCount num_entries) override;
+ void fallback_copy(void *newBuffer, const void *oldBuffer, EntryCount num_entries) override;
+ void initialize_reserved_entries(void *buffer, EntryCount reserved_entries) override;
const vespalib::alloc::MemoryAllocator* get_memory_allocator() const override;
};
diff --git a/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.cpp b/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.cpp
index 6a71388a3b9..7b54182f062 100644
--- a/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.cpp
@@ -10,7 +10,7 @@ using vespalib::alloc::MemoryAllocator;
namespace search::tensor {
SmallSubspacesBufferType::SmallSubspacesBufferType(uint32_t array_size, const AllocSpec& spec, std::shared_ptr<MemoryAllocator> memory_allocator, TensorBufferTypeMapper& type_mapper) noexcept
- : ParentType(array_size, spec.minArraysInBuffer, spec.maxArraysInBuffer, spec.numArraysForNewBuffer, spec.allocGrowFactor),
+ : ParentType(array_size, spec.min_entries_in_buffer, spec.max_entries_in_buffer, spec.num_entries_for_new_buffer, spec.allocGrowFactor),
_memory_allocator(std::move(memory_allocator)),
_ops(type_mapper.get_tensor_buffer_operations())
{
@@ -19,45 +19,45 @@ SmallSubspacesBufferType::SmallSubspacesBufferType(uint32_t array_size, const Al
SmallSubspacesBufferType::~SmallSubspacesBufferType() = default;
void
-SmallSubspacesBufferType::cleanHold(void* buffer, size_t offset, ElemCount numElems, CleanContext)
+SmallSubspacesBufferType::clean_hold(void* buffer, size_t offset, EntryCount num_entries, CleanContext)
{
- char* elem = static_cast<char *>(buffer) + offset;
- while (numElems >= getArraySize()) {
+ char* elem = static_cast<char *>(buffer) + offset * getArraySize();
+ while (num_entries >= 1) {
_ops.reclaim_labels(vespalib::ArrayRef<char>(elem, getArraySize()));
elem += getArraySize();
- numElems -= getArraySize();
+ --num_entries;
}
}
void
-SmallSubspacesBufferType::destroyElements(void *buffer, ElemCount numElems)
+SmallSubspacesBufferType::destroy_entries(void *buffer, EntryCount num_entries)
{
char* elem = static_cast<char *>(buffer);
- while (numElems >= getArraySize()) {
+ while (num_entries >= 1) {
_ops.reclaim_labels(vespalib::ArrayRef<char>(elem, getArraySize()));
elem += getArraySize();
- numElems -= getArraySize();
+ --num_entries;
}
}
void
-SmallSubspacesBufferType::fallbackCopy(void *newBuffer, const void *oldBuffer, ElemCount numElems)
+SmallSubspacesBufferType::fallback_copy(void *newBuffer, const void *oldBuffer, EntryCount num_entries)
{
- if (numElems > 0) {
- memcpy(newBuffer, oldBuffer, numElems);
+ if (num_entries > 0) {
+ memcpy(newBuffer, oldBuffer, num_entries * getArraySize());
}
const char *elem = static_cast<const char *>(oldBuffer);
- while (numElems >= getArraySize()) {
+ while (num_entries >= 1) {
_ops.copied_labels(unconstify(vespalib::ConstArrayRef<char>(elem, getArraySize())));
elem += getArraySize();
- numElems -= getArraySize();
+ --num_entries;
}
}
void
-SmallSubspacesBufferType::initializeReservedElements(void *buffer, ElemCount reservedElements)
+SmallSubspacesBufferType::initialize_reserved_entries(void *buffer, EntryCount reserved_entries)
{
- memset(buffer, 0, reservedElements);
+ memset(buffer, 0, reserved_entries * getArraySize());
}
const vespalib::alloc::MemoryAllocator*
diff --git a/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.h b/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.h
index 5622e9970b8..2f287ef1f3d 100644
--- a/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.h
+++ b/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.h
@@ -30,10 +30,10 @@ public:
SmallSubspacesBufferType& operator=(SmallSubspacesBufferType&&) noexcept = delete;
SmallSubspacesBufferType(uint32_t array_size, const AllocSpec& spec, std::shared_ptr<vespalib::alloc::MemoryAllocator> memory_allocator, TensorBufferTypeMapper& type_mapper) noexcept;
~SmallSubspacesBufferType() override;
- void cleanHold(void* buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx) override;
- void destroyElements(void *buffer, ElemCount numElems) override;
- void fallbackCopy(void *newBuffer, const void *oldBuffer, ElemCount numElems) override;
- void initializeReservedElements(void *buffer, ElemCount reservedElements) override;
+ void clean_hold(void* buffer, size_t offset, EntryCount num_entries, CleanContext cleanCtx) override;
+ void destroy_entries(void *buffer, EntryCount num_entries) override;
+ void fallback_copy(void *newBuffer, const void *oldBuffer, EntryCount num_entries) override;
+ void initialize_reserved_entries(void *buffer, EntryCount reserved_entries) override;
const vespalib::alloc::MemoryAllocator* get_memory_allocator() const override;
};
diff --git a/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.cpp b/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.cpp
new file mode 100644
index 00000000000..19c8cf6053b
--- /dev/null
+++ b/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.cpp
@@ -0,0 +1,181 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "tensor_ext_attribute.h"
+#include "serialized_tensor_ref.h"
+#include "vector_bundle.h"
+#include <vespa/eval/eval/fast_value.h>
+#include <vespa/eval/eval/tensor_spec.h>
+#include <vespa/eval/eval/value.h>
+#include <vespa/eval/eval/value_codec.h>
+#include <vespa/searchcommon/attribute/config.h>
+
+#include <vespa/log/log.h>
+LOG_SETUP(".searchlib.tensor.tensor_ext_attribute");
+
+using vespalib::eval::FastValueBuilderFactory;
+using vespalib::eval::TensorSpec;
+using vespalib::eval::TypedCells;
+using vespalib::eval::Value;
+using vespalib::eval::ValueType;
+
+namespace search::tensor {
+
+namespace {
+
+std::unique_ptr<Value>
+create_empty_tensor(const ValueType& type)
+{
+ const auto &factory = FastValueBuilderFactory::get();
+ TensorSpec empty_spec(type.to_spec());
+ return vespalib::eval::value_from_spec(empty_spec, factory);
+}
+
+}
+
+TensorExtAttribute::TensorExtAttribute(const vespalib::string& name, const Config& cfg)
+ : NotImplementedAttribute(name, cfg),
+ ITensorAttribute(),
+ IExtendAttribute(),
+ _subspace_type(cfg.tensorType()),
+ _empty(_subspace_type),
+ _empty_tensor(create_empty_tensor(cfg.tensorType()))
+{
+}
+
+TensorExtAttribute::~TensorExtAttribute() = default;
+
+const ITensorAttribute*
+TensorExtAttribute::asTensorAttribute() const
+{
+ return this;
+}
+
+void
+TensorExtAttribute::onCommit()
+{
+ LOG_ABORT("should not be reached");
+}
+
+void
+TensorExtAttribute::onUpdateStat()
+{
+}
+
+bool
+TensorExtAttribute::addDoc(DocId& docId)
+{
+ docId = _data.size();
+ _data.emplace_back(nullptr);
+ incNumDocs();
+ setCommittedDocIdLimit(getNumDocs());
+ return true;
+}
+
+bool
+TensorExtAttribute::add(const vespalib::eval::Value& v, int32_t)
+{
+ _data.back() = &v;
+ return true;
+}
+
+IExtendAttribute*
+TensorExtAttribute::getExtendInterface()
+{
+ return this;
+}
+
+TypedCells
+TensorExtAttribute::get_vector(uint32_t docid, uint32_t subspace) const
+{
+ auto vectors = get_vectors(docid);
+ return (subspace < vectors.subspaces()) ? vectors.cells(subspace) : _empty.cells();
+}
+
+VectorBundle
+TensorExtAttribute::get_vectors(uint32_t docid) const
+{
+ auto tensor = _data[docid];
+ if (tensor == nullptr) {
+ return VectorBundle();
+ }
+ return VectorBundle(tensor->cells().data, tensor->index().size(), _subspace_type);
+}
+
+std::unique_ptr<Value>
+TensorExtAttribute::getTensor(uint32_t docid) const
+{
+ auto tensor = _data[docid];
+ if (tensor == nullptr) {
+ return {};
+ }
+ return FastValueBuilderFactory::get().copy(*tensor);
+}
+
+std::unique_ptr<Value>
+TensorExtAttribute::getEmptyTensor() const
+{
+ return FastValueBuilderFactory::get().copy(*_empty_tensor);
+}
+
+TypedCells
+TensorExtAttribute::extract_cells_ref(uint32_t docid) const
+{
+ return get_vector(docid, 0);
+}
+
+const vespalib::eval::Value&
+TensorExtAttribute::get_tensor_ref(uint32_t docid) const
+{
+ auto tensor = _data[docid];
+ return (tensor == nullptr) ? *_empty_tensor : *tensor;
+}
+
+SerializedTensorRef
+TensorExtAttribute::get_serialized_tensor_ref(uint32_t) const
+{
+ notImplemented();
+}
+
+bool
+TensorExtAttribute::supports_extract_cells_ref() const
+{
+ return getConfig().tensorType().is_dense();
+}
+
+bool
+TensorExtAttribute::supports_get_tensor_ref() const
+{
+ return true;
+}
+
+bool
+TensorExtAttribute::supports_get_serialized_tensor_ref() const
+{
+ return false;
+}
+
+const ValueType&
+TensorExtAttribute::getTensorType() const
+{
+ return getConfig().tensorType();
+}
+
+TensorExtAttribute::DistanceMetric
+TensorExtAttribute::distance_metric() const
+{
+ return getConfig().distance_metric();
+}
+
+uint32_t
+TensorExtAttribute::get_num_docs() const
+{
+ return _data.size();
+}
+
+void
+TensorExtAttribute::get_state(const vespalib::slime::Inserter& inserter) const
+{
+ (void) inserter;
+}
+
+}
diff --git a/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.h b/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.h
new file mode 100644
index 00000000000..a58426cd146
--- /dev/null
+++ b/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.h
@@ -0,0 +1,54 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#pragma once
+
+#include "i_tensor_attribute.h"
+#include "empty_subspace.h"
+#include "subspace_type.h"
+#include <vespa/searchlib/attribute/not_implemented_attribute.h>
+#include <vespa/vespalib/stllike/allocator.h>
+
+namespace search::tensor {
+
+/**
+ * Attribute vector storing a pointer to single tensor value per
+ * document in streaming search. The tensor is not owned by this
+ * attribute vector.
+ */
+class TensorExtAttribute : public NotImplementedAttribute,
+ public ITensorAttribute,
+ public IExtendAttribute
+{
+ std::vector<const vespalib::eval::Value*> _data;
+ SubspaceType _subspace_type;
+ EmptySubspace _empty;
+ std::unique_ptr<vespalib::eval::Value> _empty_tensor;
+public:
+ TensorExtAttribute(const vespalib::string& name, const Config& cfg);
+ ~TensorExtAttribute() override;
+ const ITensorAttribute* asTensorAttribute() const override;
+ void onCommit() override;
+ void onUpdateStat() override;
+ bool addDoc(DocId& docId) override;
+ bool add(const vespalib::eval::Value& v, int32_t) override;
+ IExtendAttribute* getExtendInterface() override;
+ // DocVectorAccess API
+ vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const override;
+ VectorBundle get_vectors(uint32_t docid) const override;
+
+ // ITensorAttribute API
+ std::unique_ptr<vespalib::eval::Value> getTensor(uint32_t docid) const override;
+ std::unique_ptr<vespalib::eval::Value> getEmptyTensor() const override;
+ vespalib::eval::TypedCells extract_cells_ref(uint32_t docid) const override;
+ const vespalib::eval::Value& get_tensor_ref(uint32_t docid) const override;
+ SerializedTensorRef get_serialized_tensor_ref(uint32_t docid) const override;
+ bool supports_extract_cells_ref() const override;
+ bool supports_get_tensor_ref() const override;
+ bool supports_get_serialized_tensor_ref() const override;
+ const vespalib::eval::ValueType & getTensorType() const override;
+ search::attribute::DistanceMetric distance_metric() const override;
+ uint32_t get_num_docs() const override;
+ void get_state(const vespalib::slime::Inserter& inserter) const override;
+};
+
+}