func mergeHistogram()

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--
		}
	}
}