cache values to avoid dynamic dispatch inside hot loop
This commit is contained in:
parent
60750c1614
commit
127f37212b
|
@ -571,10 +571,7 @@ func MultiSearch(ctx context.Context, req *SearchRequest, indexes ...Index) (*Se
|
|||
|
||||
// sort all hits with the requested order
|
||||
if len(req.Sort) > 0 {
|
||||
sorter := &multiSearchHitSorter{
|
||||
hits: sr.Hits,
|
||||
sort: req.Sort,
|
||||
}
|
||||
sorter := newMultiSearchHitSorter(req.Sort, sr.Hits)
|
||||
sort.Sort(sorter)
|
||||
}
|
||||
|
||||
|
@ -654,13 +651,24 @@ func (f *indexAliasImplFieldDict) Close() error {
|
|||
}
|
||||
|
||||
type multiSearchHitSorter struct {
|
||||
hits search.DocumentMatchCollection
|
||||
sort search.SortOrder
|
||||
hits search.DocumentMatchCollection
|
||||
sort search.SortOrder
|
||||
cachedScoring []bool
|
||||
cachedDesc []bool
|
||||
}
|
||||
|
||||
func newMultiSearchHitSorter(sort search.SortOrder, hits search.DocumentMatchCollection) *multiSearchHitSorter {
|
||||
return &multiSearchHitSorter{
|
||||
sort: sort,
|
||||
hits: hits,
|
||||
cachedScoring: sort.CacheIsScore(),
|
||||
cachedDesc: sort.CacheDescending(),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *multiSearchHitSorter) Len() int { return len(m.hits) }
|
||||
func (m *multiSearchHitSorter) Swap(i, j int) { m.hits[i], m.hits[j] = m.hits[j], m.hits[i] }
|
||||
func (m *multiSearchHitSorter) Less(i, j int) bool {
|
||||
c := m.sort.Compare(m.hits[i], m.hits[j])
|
||||
c := m.sort.Compare(m.cachedScoring, m.cachedDesc, m.hits[i], m.hits[j])
|
||||
return c < 0
|
||||
}
|
||||
|
|
|
@ -28,8 +28,10 @@ type HeapCollector struct {
|
|||
results search.DocumentMatchCollection
|
||||
facetsBuilder *search.FacetsBuilder
|
||||
|
||||
needDocIds bool
|
||||
neededFields []string
|
||||
needDocIds bool
|
||||
neededFields []string
|
||||
cachedScoring []bool
|
||||
cachedDesc []bool
|
||||
|
||||
lowestMatchOutsideResults *search.DocumentMatch
|
||||
}
|
||||
|
@ -48,6 +50,8 @@ func NewHeapCollector(size int, skip int, sort search.SortOrder) *HeapCollector
|
|||
hc.needDocIds = true
|
||||
}
|
||||
hc.neededFields = sort.RequiredFields()
|
||||
hc.cachedScoring = sort.CacheIsScore()
|
||||
hc.cachedDesc = sort.CacheDescending()
|
||||
|
||||
return hc
|
||||
}
|
||||
|
@ -148,7 +152,7 @@ func (hc *HeapCollector) collectSingle(ctx *search.SearchContext, reader index.I
|
|||
// with this one comparision, we can avoid all heap operations if
|
||||
// this hit would have been added and then immediately removed
|
||||
if hc.lowestMatchOutsideResults != nil {
|
||||
cmp := hc.sort.Compare(d, hc.lowestMatchOutsideResults)
|
||||
cmp := hc.sort.Compare(hc.cachedScoring, hc.cachedDesc, d, hc.lowestMatchOutsideResults)
|
||||
if cmp >= 0 {
|
||||
// this hit can't possibly be in the result set, so avoid heap ops
|
||||
ctx.DocumentMatchPool.Put(d)
|
||||
|
@ -162,7 +166,7 @@ func (hc *HeapCollector) collectSingle(ctx *search.SearchContext, reader index.I
|
|||
if hc.lowestMatchOutsideResults == nil {
|
||||
hc.lowestMatchOutsideResults = removed
|
||||
} else {
|
||||
cmp := hc.sort.Compare(removed, hc.lowestMatchOutsideResults)
|
||||
cmp := hc.sort.Compare(hc.cachedScoring, hc.cachedDesc, removed, hc.lowestMatchOutsideResults)
|
||||
if cmp < 0 {
|
||||
tmp := hc.lowestMatchOutsideResults
|
||||
hc.lowestMatchOutsideResults = removed
|
||||
|
@ -239,7 +243,7 @@ func (hc *HeapCollector) Len() int {
|
|||
}
|
||||
|
||||
func (hc *HeapCollector) Less(i, j int) bool {
|
||||
so := hc.sort.Compare(hc.results[i], hc.results[j])
|
||||
so := hc.sort.Compare(hc.cachedScoring, hc.cachedDesc, hc.results[i], hc.results[j])
|
||||
return -so < 0
|
||||
}
|
||||
|
||||
|
|
|
@ -168,11 +168,11 @@ func (so SortOrder) Value(doc *DocumentMatch) {
|
|||
|
||||
// Compare will compare two document matches using the specified sort order
|
||||
// if both are numbers, we avoid converting back to term
|
||||
func (so SortOrder) Compare(i, j *DocumentMatch) int {
|
||||
func (so SortOrder) Compare(cachedScoring, cachedDesc []bool, i, j *DocumentMatch) int {
|
||||
// compare the documents on all search sorts until a differences is found
|
||||
for x, soi := range so {
|
||||
for x := range so {
|
||||
c := 0
|
||||
if soi.RequiresScoring() {
|
||||
if cachedScoring[x] {
|
||||
if i.Score < j.Score {
|
||||
c = -1
|
||||
} else if i.Score > j.Score {
|
||||
|
@ -187,7 +187,7 @@ func (so SortOrder) Compare(i, j *DocumentMatch) int {
|
|||
if c == 0 {
|
||||
continue
|
||||
}
|
||||
if soi.Descending() {
|
||||
if cachedDesc[x] {
|
||||
c = -c
|
||||
}
|
||||
return c
|
||||
|
@ -229,6 +229,22 @@ func (so SortOrder) RequiredFields() []string {
|
|||
return rv
|
||||
}
|
||||
|
||||
func (so SortOrder) CacheIsScore() []bool {
|
||||
var rv []bool
|
||||
for _, soi := range so {
|
||||
rv = append(rv, soi.RequiresScoring())
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
func (so SortOrder) CacheDescending() []bool {
|
||||
var rv []bool
|
||||
for _, soi := range so {
|
||||
rv = append(rv, soi.Descending())
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
// SortFieldType lets you control some internal sort behavior
|
||||
// normally leaving this to the zero-value of SortFieldAuto is fine
|
||||
type SortFieldType int
|
||||
|
|
Loading…
Reference in New Issue