diff options
author | Tor Egge <Tor.Egge@broadpark.no> | 2018-01-23 11:22:47 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-23 11:22:47 +0100 |
commit | e9d4490fc6843174e2409a8170cb0adf6bad6846 (patch) | |
tree | 69db9ed9ffc0f2617149acf26960067734bbb08a /searchlib | |
parent | e661ce4130b4b4bda7f9d2685cb54642b41f99ec (diff) |
Revert "Revert "Add imported tensor attribute vector""
Diffstat (limited to 'searchlib')
12 files changed, 415 insertions, 2 deletions
diff --git a/searchlib/src/tests/attribute/imported_attribute_vector/imported_attribute_vector_test.cpp b/searchlib/src/tests/attribute/imported_attribute_vector/imported_attribute_vector_test.cpp index 6406ce6d4a1..98003a69cf1 100644 --- a/searchlib/src/tests/attribute/imported_attribute_vector/imported_attribute_vector_test.cpp +++ b/searchlib/src/tests/attribute/imported_attribute_vector/imported_attribute_vector_test.cpp @@ -3,6 +3,20 @@ #include <vespa/searchlib/test/imported_attribute_fixture.h> #include <vespa/searchlib/fef/termfieldmatchdata.h> #include <vespa/searchcommon/attribute/search_context_params.h> +#include <vespa/searchlib/tensor/i_tensor_attribute.h> +#include <vespa/searchlib/tensor/tensor_attribute.h> +#include <vespa/eval/tensor/tensor_factory.h> +#include <vespa/eval/tensor/tensor.h> +#include <vespa/eval/tensor/default_tensor.h> + +using vespalib::eval::ValueType; +using vespalib::tensor::Tensor; +using vespalib::tensor::TensorCells; +using vespalib::tensor::DenseTensorCells; +using vespalib::tensor::TensorDimensions; +using vespalib::tensor::TensorFactory; +using search::tensor::TensorAttribute; +using search::tensor::ITensorAttribute; namespace search { namespace attribute { @@ -534,6 +548,89 @@ TEST("onSerializeForDescendingSort() is forwarded with remapped LID to target ve SerializeFixture<ReadGuardSingleStringAttrFixture>>()); } +template <bool useReadGuard = false> +struct TensorAttrFixtureBase : FixtureBase<useReadGuard> { + vespalib::tensor::DefaultTensor::builder builder; + std::shared_ptr<Tensor> tensor1; + std::shared_ptr<Tensor> tensor2; + + TensorAttrFixtureBase(bool dense) + : FixtureBase<useReadGuard>(), + builder(), + tensor1(), + tensor2() + { + setup(dense); + } + Tensor::UP createTensor(const TensorCells &cells, + const TensorDimensions &dimensions) { + return TensorFactory::create(cells, dimensions, builder); + } + Tensor::UP createDenseTensor(const DenseTensorCells &cells) const { + return TensorFactory::createDense(cells); + } + void setup(bool dense) { + if (dense) { + tensor1 = createDenseTensor({ {{{"x",1}}, 11} }); + tensor2 = createDenseTensor({ {{{"x",0}}, 12}, {{{"x", 1}}, 0} }); + } else { + tensor1 = createTensor({ {{{"x","1"}}, 11} }, { "x" }); + tensor2 = createTensor({ {{{"x","0"}}, 12} }, { "x" }); + } + const std::vector<ImportedAttributeFixture::LidToLidMapping<std::shared_ptr<Tensor>>> mappings = + { {DocId(2), dummy_gid(3), DocId(3), tensor1 }, + {DocId(4), dummy_gid(7), DocId(7), tensor2 } }; + this->template reset_with_tensor_reference_mappings<TensorAttribute, std::shared_ptr<Tensor>>( + ValueType::from_spec(dense ? "tensor(x[2])" : "tensor(x{})"), + mappings); + } + Tensor::UP getTensor(DocId docId) { + const ITensorAttribute & tensorAttr = dynamic_cast<const ITensorAttribute &>(*this->get_imported_attr()); + return tensorAttr.getTensor(docId); + } + void assertNoTensor(DocId docId) { + auto tensor = getTensor(docId); + EXPECT_TRUE(!tensor); + } + void assertTensor(DocId docId, const Tensor &expTensor) { + auto tensor = getTensor(docId); + ASSERT_TRUE(!!tensor); + EXPECT_EQUAL(expTensor, *tensor); + } + void assertTensors() { + assertNoTensor(0); + assertNoTensor(1); + assertTensor(2, *tensor1); + assertNoTensor(3); + assertTensor(4, *tensor2); + } +}; + +using TensorAttrFixture = TensorAttrFixtureBase<false>; +using ReadGuardTensorAttrFixture = TensorAttrFixtureBase<true>; + + + +TEST_F("Imported sparse tensor", TensorAttrFixture(false)) +{ + f.assertTensors(); +} + +TEST_F("Imported dense tensor", TensorAttrFixture(true)) +{ + f.assertTensors(); +} + +TEST_F("Imported sparse tensor read guard", ReadGuardTensorAttrFixture(false)) +{ + f.assertTensors(); +} + +TEST_F("Imported dense tensor read guard", ReadGuardTensorAttrFixture(true)) +{ + f.assertTensors(); +} + } // attribute } // search diff --git a/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt b/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt index e99092f0206..cc6736e21c5 100644 --- a/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt +++ b/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt @@ -47,6 +47,7 @@ vespa_add_library(searchlib_attribute OBJECT iattributemanager.cpp iattributesavetarget.cpp imported_attribute_vector.cpp + imported_attribute_vector_factory.cpp imported_attribute_vector_read_guard.cpp imported_search_context.cpp integerbase.cpp diff --git a/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector.h b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector.h index 7d272c42d9e..324ce4ec12b 100644 --- a/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector.h +++ b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector.h @@ -86,7 +86,7 @@ public: /* * Create an imported attribute with a snapshot of lid to lid mapping. */ - std::unique_ptr<ImportedAttributeVector> makeReadGuard(bool stableEnumGuard) const; + virtual std::unique_ptr<ImportedAttributeVector> makeReadGuard(bool stableEnumGuard) const; protected: long onSerializeForAscendingSort(DocId doc, void * serTo, long available, const common::BlobConverter * bc) const override; diff --git a/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_factory.cpp b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_factory.cpp new file mode 100644 index 00000000000..8161abe61f4 --- /dev/null +++ b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_factory.cpp @@ -0,0 +1,51 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "imported_attribute_vector_factory.h" +#include "imported_attribute_vector.h" +#include <vespa/searchlib/tensor/imported_tensor_attribute_vector.h> + +namespace search::attribute { + +using search::tensor::ImportedTensorAttributeVector; + +namespace { + +BasicType::Type getBasicType(const std::shared_ptr<AttributeVector> &attr) +{ + return attr ? attr->getBasicType() : BasicType::Type::NONE; +} + +} + +std::shared_ptr<ImportedAttributeVector> +ImportedAttributeVectorFactory::create(vespalib::stringref name, + std::shared_ptr<ReferenceAttribute> reference_attribute, + std::shared_ptr<AttributeVector> target_attribute, + std::shared_ptr<IDocumentMetaStoreContext> document_meta_store, + bool use_search_cache) +{ + switch (getBasicType(target_attribute)) { + case BasicType::Type::TENSOR: + return std::make_shared<ImportedTensorAttributeVector>(name, std::move(reference_attribute), std::move(target_attribute), std::move(document_meta_store), use_search_cache); + default: + return std::make_shared<ImportedAttributeVector>(name, std::move(reference_attribute), std::move(target_attribute), std::move(document_meta_store), use_search_cache); + } +} + + +std::shared_ptr<ImportedAttributeVector> +ImportedAttributeVectorFactory::create(vespalib::stringref name, + std::shared_ptr<ReferenceAttribute> reference_attribute, + std::shared_ptr<AttributeVector> target_attribute, + std::shared_ptr<IDocumentMetaStoreContext> document_meta_store, + std::shared_ptr<BitVectorSearchCache> search_cache) +{ + switch (getBasicType(target_attribute)) { + case BasicType::Type::TENSOR: + return std::make_shared<ImportedTensorAttributeVector>(name, std::move(reference_attribute), std::move(target_attribute), std::move(document_meta_store), std::move(search_cache)); + default: + return std::make_shared<ImportedAttributeVector>(name, std::move(reference_attribute), std::move(target_attribute), std::move(document_meta_store), std::move(search_cache)); + } +} + +} // search::attribute diff --git a/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_factory.h b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_factory.h new file mode 100644 index 00000000000..363fb9f29bc --- /dev/null +++ b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_factory.h @@ -0,0 +1,41 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include <vespa/vespalib/stllike/string.h> +#include <memory> + +namespace search { + +class AttributeVector; +class IDocumentMetaStoreContext; + +namespace attribute { + +class BitVectorSearchCache; +class ImportedAttributeVector; +class ReferenceAttribute; + +/* + * Factory class used to create proper imported attribute vector based + * on target attribute basic type. + */ +class ImportedAttributeVectorFactory { +public: + static std::shared_ptr<ImportedAttributeVector> + create(vespalib::stringref name, + std::shared_ptr<ReferenceAttribute> reference_attribute, + std::shared_ptr<AttributeVector> target_attribute, + std::shared_ptr<IDocumentMetaStoreContext> document_meta_store, + bool use_search_cache); + + static std::shared_ptr<ImportedAttributeVector> + create(vespalib::stringref name, + std::shared_ptr<ReferenceAttribute> reference_attribute, + std::shared_ptr<AttributeVector> target_attribute, + std::shared_ptr<IDocumentMetaStoreContext> document_meta_store, + std::shared_ptr<BitVectorSearchCache> search_cache); +}; + +} // attribute +} // search diff --git a/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_read_guard.h b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_read_guard.h index 2ca8680f4b8..a0c24e3b8eb 100644 --- a/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_read_guard.h +++ b/searchlib/src/vespa/searchlib/attribute/imported_attribute_vector_read_guard.h @@ -26,6 +26,7 @@ class ImportedAttributeVectorReadGuard : public ImportedAttributeVector AttributeEnumGuard _target_attribute_enum_guard; std::unique_ptr<IGidToLidMapper> _mapper; +protected: uint32_t getReferencedLid(uint32_t lid) const { return _referencedLids[lid]; } diff --git a/searchlib/src/vespa/searchlib/tensor/CMakeLists.txt b/searchlib/src/vespa/searchlib/tensor/CMakeLists.txt index f0c8832d0ef..ea5d30d9a47 100644 --- a/searchlib/src/vespa/searchlib/tensor/CMakeLists.txt +++ b/searchlib/src/vespa/searchlib/tensor/CMakeLists.txt @@ -6,6 +6,8 @@ vespa_add_library(searchlib_tensor OBJECT dense_tensor_store.cpp generic_tensor_attribute.cpp generic_tensor_store.cpp + imported_tensor_attribute_vector.cpp + imported_tensor_attribute_vector_read_guard.cpp tensor_attribute.cpp generic_tensor_attribute_saver.cpp tensor_store.cpp diff --git a/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector.cpp b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector.cpp new file mode 100644 index 00000000000..066978f4e50 --- /dev/null +++ b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector.cpp @@ -0,0 +1,72 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "imported_tensor_attribute_vector.h" +#include "imported_tensor_attribute_vector_read_guard.h" +#include <vespa/eval/tensor/tensor.h> + +namespace search::tensor { + +using vespalib::tensor::Tensor; + +ImportedTensorAttributeVector::ImportedTensorAttributeVector(vespalib::stringref name, + std::shared_ptr<ReferenceAttribute> reference_attribute, + std::shared_ptr<AttributeVector> target_attribute, + std::shared_ptr<IDocumentMetaStoreContext> document_meta_store, + bool use_search_cache) + : ImportedAttributeVector(name, std::move(reference_attribute), + std::move(target_attribute), + std::move(document_meta_store), + use_search_cache), + _target_tensor_attribute(dynamic_cast<const ITensorAttribute &>(*_target_attribute)) +{ +} + +ImportedTensorAttributeVector::ImportedTensorAttributeVector(vespalib::stringref name, + std::shared_ptr<ReferenceAttribute> reference_attribute, + std::shared_ptr<AttributeVector> target_attribute, + std::shared_ptr<IDocumentMetaStoreContext> document_meta_store, + std::shared_ptr<BitVectorSearchCache> search_cache) + : ImportedAttributeVector(name, std::move(reference_attribute), + std::move(target_attribute), + std::move(document_meta_store), + std::move(search_cache)), + _target_tensor_attribute(dynamic_cast<const ITensorAttribute &>(*_target_attribute)) +{ +} + +ImportedTensorAttributeVector::~ImportedTensorAttributeVector() +{ +} + +std::unique_ptr<attribute::ImportedAttributeVector> +ImportedTensorAttributeVector::makeReadGuard(bool stableEnumGuard) const +{ + return std::make_unique<ImportedTensorAttributeVectorReadGuard> + (getName(), getReferenceAttribute(), getTargetAttribute(), getDocumentMetaStore(), getSearchCache(), stableEnumGuard); +} + +std::unique_ptr<Tensor> +ImportedTensorAttributeVector::getTensor(uint32_t docId) const +{ + return _target_tensor_attribute.getTensor(_reference_attribute->getReferencedLid(docId)); +} + +std::unique_ptr<Tensor> +ImportedTensorAttributeVector::getEmptyTensor() const +{ + return _target_tensor_attribute.getEmptyTensor(); +} + +void +ImportedTensorAttributeVector::getTensor(uint32_t docId, vespalib::tensor::MutableDenseTensorView &tensor) const +{ + _target_tensor_attribute.getTensor(_reference_attribute->getReferencedLid(docId), tensor); +} + +vespalib::eval::ValueType +ImportedTensorAttributeVector::getTensorType() const +{ + return _target_tensor_attribute.getTensorType(); +} + +} diff --git a/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector.h b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector.h new file mode 100644 index 00000000000..86a434cc7ae --- /dev/null +++ b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector.h @@ -0,0 +1,39 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include <vespa/searchlib/attribute/imported_attribute_vector.h> +#include "i_tensor_attribute.h" + +namespace search::tensor { + +/** + * Attribute vector for imported tensor attributes. + */ +class ImportedTensorAttributeVector : public attribute::ImportedAttributeVector, + public ITensorAttribute +{ + using ReferenceAttribute = attribute::ReferenceAttribute; + using BitVectorSearchCache = attribute::BitVectorSearchCache; + const ITensorAttribute &_target_tensor_attribute; +public: + ImportedTensorAttributeVector(vespalib::stringref name, + std::shared_ptr<ReferenceAttribute> reference_attribute, + std::shared_ptr<AttributeVector> target_attribute, + std::shared_ptr<IDocumentMetaStoreContext> document_meta_store, + bool use_search_cache); + ImportedTensorAttributeVector(vespalib::stringref name, + std::shared_ptr<ReferenceAttribute> reference_attribute, + std::shared_ptr<AttributeVector> target_attribute, + std::shared_ptr<IDocumentMetaStoreContext> document_meta_store, + std::shared_ptr<BitVectorSearchCache> search_cache); + ~ImportedTensorAttributeVector(); + + virtual std::unique_ptr<attribute::ImportedAttributeVector> makeReadGuard(bool stableEnumGuard) const override; + virtual std::unique_ptr<Tensor> getTensor(uint32_t docId) const override; + virtual std::unique_ptr<Tensor> getEmptyTensor() const override; + virtual void getTensor(uint32_t docId, vespalib::tensor::MutableDenseTensorView &tensor) const override; + virtual vespalib::eval::ValueType getTensorType() const override; +}; + +} // namespace search::tensor diff --git a/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.cpp b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.cpp new file mode 100644 index 00000000000..0678428d2c2 --- /dev/null +++ b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.cpp @@ -0,0 +1,53 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "imported_tensor_attribute_vector_read_guard.h" +#include <vespa/eval/tensor/tensor.h> + +namespace search::tensor { + +using vespalib::tensor::Tensor; + +ImportedTensorAttributeVectorReadGuard::ImportedTensorAttributeVectorReadGuard(vespalib::stringref name, + std::shared_ptr<ReferenceAttribute> reference_attribute, + std::shared_ptr<AttributeVector> target_attribute, + std::shared_ptr<IDocumentMetaStoreContext> document_meta_store, + std::shared_ptr<BitVectorSearchCache> search_cache, + bool stableEnumGuard) + : ImportedAttributeVectorReadGuard(name, std::move(reference_attribute), + std::move(target_attribute), + std::move(document_meta_store), + std::move(search_cache), + stableEnumGuard), + _target_tensor_attribute(dynamic_cast<const ITensorAttribute &>(*_target_attribute)) +{ +} + +ImportedTensorAttributeVectorReadGuard::~ImportedTensorAttributeVectorReadGuard() +{ +} + +std::unique_ptr<Tensor> +ImportedTensorAttributeVectorReadGuard::getTensor(uint32_t docId) const +{ + return _target_tensor_attribute.getTensor(getReferencedLid(docId)); +} + +std::unique_ptr<Tensor> +ImportedTensorAttributeVectorReadGuard::getEmptyTensor() const +{ + return _target_tensor_attribute.getEmptyTensor(); +} + +void +ImportedTensorAttributeVectorReadGuard::getTensor(uint32_t docId, vespalib::tensor::MutableDenseTensorView &tensor) const +{ + _target_tensor_attribute.getTensor(getReferencedLid(docId), tensor); +} + +vespalib::eval::ValueType +ImportedTensorAttributeVectorReadGuard::getTensorType() const +{ + return _target_tensor_attribute.getTensorType(); +} + +} diff --git a/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.h b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.h new file mode 100644 index 00000000000..139f35d1fba --- /dev/null +++ b/searchlib/src/vespa/searchlib/tensor/imported_tensor_attribute_vector_read_guard.h @@ -0,0 +1,37 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include <vespa/searchlib/attribute/imported_attribute_vector_read_guard.h> +#include "i_tensor_attribute.h" + +namespace search::tensor { + +/** + * Short lived attribute vector for imported tensor attributes. + * + * Extra information for direct lid to referenced lid mapping with + * boundary check is setup during construction. + */ +class ImportedTensorAttributeVectorReadGuard : public attribute::ImportedAttributeVectorReadGuard, + public ITensorAttribute +{ + using ReferenceAttribute = attribute::ReferenceAttribute; + using BitVectorSearchCache = attribute::BitVectorSearchCache; + const ITensorAttribute &_target_tensor_attribute; +public: + ImportedTensorAttributeVectorReadGuard(vespalib::stringref name, + std::shared_ptr<ReferenceAttribute> reference_attribute, + std::shared_ptr<AttributeVector> target_attribute, + std::shared_ptr<IDocumentMetaStoreContext> document_meta_store, + std::shared_ptr<BitVectorSearchCache> search_cache, + bool stableEnumGuard); + ~ImportedTensorAttributeVectorReadGuard(); + + virtual std::unique_ptr<Tensor> getTensor(uint32_t docId) const override; + virtual std::unique_ptr<Tensor> getEmptyTensor() const override; + virtual void getTensor(uint32_t docId, vespalib::tensor::MutableDenseTensorView &tensor) const override; + virtual vespalib::eval::ValueType getTensorType() const override; +}; + +} // namespace search::tensor diff --git a/searchlib/src/vespa/searchlib/test/imported_attribute_fixture.h b/searchlib/src/vespa/searchlib/test/imported_attribute_fixture.h index f9e3de79144..e49509a444f 100644 --- a/searchlib/src/vespa/searchlib/test/imported_attribute_fixture.h +++ b/searchlib/src/vespa/searchlib/test/imported_attribute_fixture.h @@ -9,6 +9,7 @@ #include <vespa/searchlib/attribute/attributeguard.h> #include <vespa/searchlib/attribute/floatbase.h> #include <vespa/searchlib/attribute/imported_attribute_vector.h> +#include <vespa/searchlib/attribute/imported_attribute_vector_factory.h> #include <vespa/searchlib/attribute/integerbase.h> #include <vespa/searchlib/attribute/not_implemented_attribute.h> #include <vespa/searchlib/attribute/stringbase.h> @@ -113,6 +114,15 @@ std::shared_ptr<AttrVecType> create_wset_attribute(BasicType type, return create_typed_attribute<AttrVecType>(type, CollectionType::WSET, fast_search, FilterConfig::Default, name); } +template<typename AttrVecType> +std::shared_ptr<AttrVecType> create_tensor_attribute(const vespalib::eval::ValueType &tensorType, + vespalib::stringref name = "parent") { + Config cfg(BasicType::Type::TENSOR, CollectionType::Type::SINGLE); + cfg.setTensorType(tensorType); + return std::dynamic_pointer_cast<AttrVecType>( + AttributeFactory::createAttribute(name, std::move(cfg))); +} + template<typename VectorType> void add_n_docs_with_undefined_values(VectorType &vec, size_t n) { vec.addDocs(n); @@ -157,7 +167,7 @@ struct ImportedAttributeFixture { std::shared_ptr<ImportedAttributeVector> create_attribute_vector_from_members(vespalib::stringref name = default_imported_attr_name()) { - return std::make_shared<ImportedAttributeVector>(name, reference_attr, target_attr, document_meta_store, use_search_cache); + return ImportedAttributeVectorFactory::create(name, reference_attr, target_attr, document_meta_store, use_search_cache); } template<typename AttrVecType> @@ -246,6 +256,15 @@ struct ImportedAttributeFixture { } }); } + + template<typename AttrVecType, typename ValueType> + void reset_with_tensor_reference_mappings(const vespalib::eval::ValueType &tensorType, + const std::vector<LidToLidMapping<ValueType>> &mappings) { + reset_with_new_target_attr(create_tensor_attribute<AttrVecType>(tensorType)); + set_up_and_map<AttrVecType>(mappings, [this](auto &target_vec, auto &mapping) { + target_vec.setTensor(mapping._to_lid, *mapping._value_in_target_attr); + }); + } }; ImportedAttributeFixture::ImportedAttributeFixture(bool use_search_cache_) |