in aggregators/merger.go [346:413]
func mergeHistogram(to, from *aggregationpb.HDRHistogram) {
if len(from.Buckets) == 0 {
return
}
if len(to.Buckets) == 0 {
to.Buckets = append(to.Buckets, from.Buckets...)
to.Counts = append(to.Counts, from.Counts...)
return
}
startToIdx, found := sort.Find(len(to.Buckets), func(i int) int {
return int(from.Buckets[0] - to.Buckets[i])
})
if found && len(from.Buckets) == 1 {
// optimize for single value of `from` also found in `to`
to.Counts[startToIdx] += from.Counts[0]
return
}
// Since all values of `from` must be greater than the first value, we can
// limit the search space in `to` to [startToIdx, len(to.Buckets))
requiredLen := len(to.Buckets) + len(from.Buckets)
for toIdx, fromIdx := startToIdx, 0; toIdx < len(to.Buckets) && fromIdx < len(from.Buckets); {
v := to.Buckets[toIdx] - from.Buckets[fromIdx]
switch {
case v == 0:
// For every bucket that is common, we need one less bucket in final slice
requiredLen--
toIdx++
fromIdx++
case v < 0:
toIdx++
case v > 0:
fromIdx++
}
}
toIdx, fromIdx := len(to.Buckets)-1, len(from.Buckets)-1
to.Buckets = slices.Grow(to.Buckets, requiredLen-len(to.Buckets))[:requiredLen]
to.Counts = slices.Grow(to.Counts, requiredLen-len(to.Counts))[:requiredLen]
for idx := len(to.Buckets) - 1; idx >= 0; idx-- {
if fromIdx < 0 {
break
}
if toIdx < startToIdx {
copy(to.Counts[startToIdx:idx+1], from.Counts[0:fromIdx+1])
copy(to.Buckets[startToIdx:idx+1], from.Buckets[0:fromIdx+1])
break
}
v := to.Buckets[toIdx] - from.Buckets[fromIdx]
switch {
case v == 0:
to.Counts[idx] = to.Counts[toIdx] + from.Counts[fromIdx]
to.Buckets[idx] = to.Buckets[toIdx]
toIdx--
fromIdx--
case v > 0:
to.Counts[idx] = to.Counts[toIdx]
to.Buckets[idx] = to.Buckets[toIdx]
toIdx--
case v < 0:
to.Counts[idx] = from.Counts[fromIdx]
to.Buckets[idx] = from.Buckets[fromIdx]
fromIdx--
}
}
}