diff options
10 files changed, 35 insertions, 17 deletions
diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java index 999846d1755..2eec7109722 100644 --- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java +++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java @@ -271,12 +271,14 @@ public class FastHit extends Hit { public void addSummary(Docsum docsum) { LazyDocsumValue lazyDocsumValue = new LazyDocsumValue(docsum); + reserve(docsum.getDefinition().getFieldCount()); for (DocsumField field : docsum.getDefinition().getFields()) { setDocsumFieldIfNotPresent(field.getName(), lazyDocsumValue); } } void addSummary(DocsumDefinition docsumDef, Inspector value) { + reserve(docsumDef.getFieldCount()); for (DocsumField field : docsumDef.getFields()) { String fieldName = field.getName(); if (value.type() == Type.STRING && diff --git a/container-search/src/main/java/com/yahoo/search/dispatch/Dispatcher.java b/container-search/src/main/java/com/yahoo/search/dispatch/Dispatcher.java index b03c0cb752f..6b4d3594087 100644 --- a/container-search/src/main/java/com/yahoo/search/dispatch/Dispatcher.java +++ b/container-search/src/main/java/com/yahoo/search/dispatch/Dispatcher.java @@ -227,6 +227,7 @@ public class Dispatcher extends AbstractComponent { } private void fill(FastHit hit, Inspector summary) { + hit.reserve(summary.fieldCount()); summary.traverse((String name, Inspector value) -> { hit.setField(name, nativeTypeOf(value)); }); diff --git a/container-search/src/main/java/com/yahoo/search/result/Hit.java b/container-search/src/main/java/com/yahoo/search/result/Hit.java index 815006edbf5..0bfbecfd9ab 100644 --- a/container-search/src/main/java/com/yahoo/search/result/Hit.java +++ b/container-search/src/main/java/com/yahoo/search/result/Hit.java @@ -101,8 +101,12 @@ public class Hit extends ListenableFreezableClass implements Data, Comparable<Hi public static final String SDDOCNAME_FIELD = "sddocname"; private Map<String,Object> getFieldMap() { + return getFieldMap(16); + } + private Map<String,Object> getFieldMap(int minSize) { if (fields == null) { - fields = new LinkedHashMap<>(16); + // Compensate for loadfactor and then some, rounded up.... + fields = new LinkedHashMap<>(2*minSize); } return fields; } @@ -448,6 +452,14 @@ public class Hit extends ListenableFreezableClass implements Data, Comparable<Hi public final Map<String,Object> fields() { return getUnmodifiableFieldMap(); } /** + * Will preallocate in order to avoid resizing. + * @param minSize + */ + public void reserve(int minSize) { + getFieldMap(minSize); + } + + /** * Fields * @return An iterator for traversing the fields * @since 5.1.3 diff --git a/searchcore/src/tests/proton/matching/matching_test.cpp b/searchcore/src/tests/proton/matching/matching_test.cpp index deadafcad8f..679108ba872 100644 --- a/searchcore/src/tests/proton/matching/matching_test.cpp +++ b/searchcore/src/tests/proton/matching/matching_test.cpp @@ -494,11 +494,11 @@ TEST("require that sortspec can be used (multi-threaded)") { SearchReply::UP reply = world.performSearch(request, threads); ASSERT_EQUAL(9u, reply->hits.size()); EXPECT_EQUAL(document::DocumentId("doc::100").getGlobalId(), reply->hits[0].gid); - EXPECT_EQUAL(0.0, reply->hits[0].metric); + EXPECT_EQUAL(default_rank_value, reply->hits[0].metric); EXPECT_EQUAL(document::DocumentId("doc::200").getGlobalId(), reply->hits[1].gid); - EXPECT_EQUAL(0.0, reply->hits[1].metric); + EXPECT_EQUAL(default_rank_value, reply->hits[1].metric); EXPECT_EQUAL(document::DocumentId("doc::300").getGlobalId(), reply->hits[2].gid); - EXPECT_EQUAL(0.0, reply->hits[2].metric); + EXPECT_EQUAL(default_rank_value, reply->hits[2].metric); } } diff --git a/searchcore/src/vespa/searchcore/proton/matching/match_thread.h b/searchcore/src/vespa/searchcore/proton/matching/match_thread.h index cd01c330931..2d056d0e761 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/match_thread.h +++ b/searchcore/src/vespa/searchcore/proton/matching/match_thread.h @@ -53,7 +53,7 @@ private: Context(double rankDropLimit, MatchTools &matchTools, RankProgram & ranking, HitCollector & hits, uint32_t num_threads) __attribute__((noinline)); void rankHit(uint32_t docId); - void addHit(uint32_t docId) { _hits.addHit(docId, 0.0); } + void addHit(uint32_t docId) { _hits.addHit(docId, search::default_rank_value); } bool isBelowLimit() const { return matches < _matches_limit; } bool isAtLimit() const { return matches == _matches_limit; } bool atSoftDoom() const { return _softDoom.doom(); } diff --git a/searchlib/src/tests/hitcollector/hitcollector_test.cpp b/searchlib/src/tests/hitcollector/hitcollector_test.cpp index b38f5cdb168..3f49c6969a0 100644 --- a/searchlib/src/tests/hitcollector/hitcollector_test.cpp +++ b/searchlib/src/tests/hitcollector/hitcollector_test.cpp @@ -30,7 +30,7 @@ struct PredefinedScorer : public HitCollector::DocumentScorer ScoreMap _scores; PredefinedScorer(const ScoreMap &scores) : _scores(scores) {} virtual feature_t score(uint32_t docId) override { - feature_t retval = 0.0; + feature_t retval = default_rank_value; auto itr = _scores.find(docId); if (itr != _scores.end()) { retval = itr->second; @@ -436,7 +436,7 @@ TEST_F("require that result set is merged correctly with first phase ranking", expRh.push_back(RankedHit()); expRh.back()._docId = i; // only the maxHitsSize best hits gets a score - expRh.back()._rankValue = (i < f.numDocs - f.maxHitsSize) ? 0 : i + 1000; + expRh.back()._rankValue = (i < f.numDocs - f.maxHitsSize) ? default_rank_value : i + 1000; } std::unique_ptr<ResultSet> rs = f.hc.getResultSet(); TEST_DO(checkResult(*rs.get(), expRh)); @@ -448,7 +448,7 @@ addExpectedHitForMergeTest(const MergeResultSetFixture &f, std::vector<RankedHit expRh.push_back(RankedHit()); expRh.back()._docId = docId; if (docId < f.numDocs - f.maxHitsSize) { // only the maxHitsSize best hits gets a score - expRh.back()._rankValue = 0; + expRh.back()._rankValue = default_rank_value; } else if (docId < f.numDocs - f.maxHeapSize) { // only first phase ranking expRh.back()._rankValue = docId + 500; // adjusted with - 500 } else { // second phase ranking on the maxHeapSize best hits @@ -497,7 +497,7 @@ TEST("require that hits can be added out of order when passing array limit") { for (uint32_t i = 0; i < numHits; ++i) { expRh.push_back(RankedHit()); expRh.back()._docId = i; - expRh.back()._rankValue = (i < 50) ? 0 : (i + 100); + expRh.back()._rankValue = (i < 50) ? default_rank_value : (i + 100); } // add results in reverse order for (uint32_t i = numHits; i-- > 0; ) { @@ -516,7 +516,7 @@ TEST("require that hits can be added out of order only after passing array limit for (uint32_t i = 0; i < numHits; ++i) { expRh.push_back(RankedHit()); expRh.back()._docId = i; - expRh.back()._rankValue = (i < 50) ? 0 : (i + 100); + expRh.back()._rankValue = (i < 50) ? default_rank_value : (i + 100); } // add results in reverse order const uint32_t numInOrder = numHits - 30; diff --git a/searchlib/src/vespa/searchlib/common/hitrank.h b/searchlib/src/vespa/searchlib/common/hitrank.h index abc714660cf..9f40cf9277c 100644 --- a/searchlib/src/vespa/searchlib/common/hitrank.h +++ b/searchlib/src/vespa/searchlib/common/hitrank.h @@ -2,10 +2,13 @@ #pragma once +#include <cmath> + namespace search { typedef double HitRank; typedef double SignedHitRank; +constexpr HitRank default_rank_value = -HUGE_VAL; } // namespace search diff --git a/searchlib/src/vespa/searchlib/common/rankedhit.h b/searchlib/src/vespa/searchlib/common/rankedhit.h index bd66f884a08..d56fa92442f 100644 --- a/searchlib/src/vespa/searchlib/common/rankedhit.h +++ b/searchlib/src/vespa/searchlib/common/rankedhit.h @@ -11,8 +11,8 @@ namespace search { struct RankedHit { - RankedHit() : _docId(0), _rankValue(0) { } - RankedHit(unsigned int docId, HitRank rank=0.0) : _docId(docId), _rankValue(rank) { } + RankedHit() : _docId(0), _rankValue(default_rank_value) { } + RankedHit(unsigned int docId, HitRank rank = default_rank_value) : _docId(docId), _rankValue(rank) { } unsigned int getDocId() const { return _docId & 0x7fffffff; } bool hasMore() const { return _docId & 0x80000000; } HitRank getRank() const { return _rankValue; } diff --git a/searchlib/src/vespa/searchlib/common/resultset.cpp b/searchlib/src/vespa/searchlib/common/resultset.cpp index 69f3b13d709..5ad89bf49d7 100644 --- a/searchlib/src/vespa/searchlib/common/resultset.cpp +++ b/searchlib/src/vespa/searchlib/common/resultset.cpp @@ -111,7 +111,7 @@ ResultSet::mergeWithBitOverflow() // bitvector hits before array hits while (bidx < firstArrayHit) { tgtA->_docId = bidx; - tgtA->_rankValue = 0; + tgtA->_rankValue = default_rank_value; tgtA++; bidx = bitVector->getNextTrueBit(bidx + 1); } @@ -123,7 +123,7 @@ ResultSet::mergeWithBitOverflow() tgtA->_rankValue = oldA->_rankValue; oldA++; } else { - tgtA->_rankValue = 0; + tgtA->_rankValue = default_rank_value; } tgtA++; bidx = bitVector->getNextTrueBit(bidx + 1); @@ -134,7 +134,7 @@ ResultSet::mergeWithBitOverflow() // bitvector hits after array hits while (tgtA < tgtAEnd) { tgtA->_docId = bidx; - tgtA->_rankValue = 0; + tgtA->_rankValue = default_rank_value; tgtA++; bidx = bitVector->getNextTrueBit(bidx + 1); } diff --git a/searchlib/src/vespa/searchlib/queryeval/hitcollector.cpp b/searchlib/src/vespa/searchlib/queryeval/hitcollector.cpp index 3601a93fdc2..7d79d0f659e 100644 --- a/searchlib/src/vespa/searchlib/queryeval/hitcollector.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/hitcollector.cpp @@ -306,7 +306,7 @@ HitCollector::getResultSet() rh[j]._rankValue = getReScore(_hits[i].second); ++i; } else { - rh[j]._rankValue = 0; + rh[j]._rankValue = default_rank_value; } } } else { @@ -317,7 +317,7 @@ HitCollector::getResultSet() rh[j]._rankValue = _hits[i].second; ++i; } else { - rh[j]._rankValue = 0; + rh[j]._rankValue = default_rank_value; } } } |