Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functions that allow to efficiently merge and downsample expo histograms #12328

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,62 @@ func copy{{ .structName }}(dst, src []{{ .itemType }}) []{{ .itemType }} {
dst = dst[:0]
return append(dst, src...)
}

{{- if ne .itemType "string" }}
// TryIncrementFrom increments all elements from the current slice by the elements from another slice
// if it has enough capacity for the other slice's length plus the offset.
// If there isn't enough capacity, this method returns false and the slice is not mutated.
func (ms {{ .structName }}) TryIncrementFrom(other {{ .structName }}, offset int) bool {
if offset < 0 {
return false
}
ms.getState().AssertMutable()
newLen := max(ms.Len(), other.Len()+offset)
ours := *ms.getOrig()
if cap(ours) < newLen {
return false
}
ours = ours[:newLen]
theirs := *other.getOrig()
for i := 0; i < len(theirs); i++ {
ours[i+offset] += theirs[i]
}
*ms.getOrig() = ours
return true
}


// Collapse merges (sums) n adjacent buckets and reslices to account for the decreased length
//
// n=2 offset=1
// before: 1 1 1 1 1 1 1 1
// V V V V V
// after: 1 2 2 2 1
func (ms {{ .structName }}) Collapse(n, offset int) {
ms.getState().AssertMutable()
if offset >= n || offset < 0 {
panic(fmt.Sprintf("offset %d must be positive and smaller than n %d", offset, n))
}
if n < 2 {
return
}
orig := *ms.getOrig()
newLen := (len(orig) + offset) / n
if (len(orig)+offset)%n != 0 {
newLen++
}

for i := 0; i < newLen; i++ {
if offset == 0 || i > 0 {
orig[i] = orig[i*n-offset]
}
for j := i*n + 1 - offset; j < i*n+n-offset && j < len(orig); j++ {
if j > 0 {
orig[i] += orig[j]
}
}
}

*ms.getOrig() = orig[:newLen]
}
{{- end }}
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,61 @@ func Test{{ .structName }}EnsureCapacity(t *testing.T) {
ms.EnsureCapacity(2)
assert.Equal(t, 4, cap(*ms.getOrig()))
}

{{- if ne .itemType "string" }}

func Test{{ .structName }}TryIncrementFrom(t *testing.T) {
ms := New{{ .structName }}()
ms.FromRaw([]{{ .itemType }}{10, 9})

ms2 := New{{ .structName }}()
ms2.FromRaw([]{{ .itemType }}{1, 10})

assert.False(t, ms.TryIncrementFrom(ms2, 1))
ms.EnsureCapacity(4)
assert.True(t, ms.TryIncrementFrom(ms2, 1))
{{- if eq .itemType "float64" }}
assert.InDelta(t, {{ .itemType }}(10), ms.At(0), 0.01)
assert.InDelta(t, {{ .itemType }}(10), ms.At(1), 0.01)
assert.InDelta(t, {{ .itemType }}(10), ms.At(2), 0.01)
{{- else }}
assert.Equal(t, {{ .itemType }}(10), ms.At(0))
assert.Equal(t, {{ .itemType }}(10), ms.At(1))
assert.Equal(t, {{ .itemType }}(10), ms.At(2))
{{- end }}
}

func Test{{ .structName }}Collapse(t *testing.T) {
ms := New{{ .structName }}()
ms.FromRaw([]{{ .itemType }}{1, 1, 1, 1, 1, 1})

ms.Collapse(4, 0)

assert.Equal(t, 2, ms.Len())
{{- if eq .itemType "float64" }}
assert.InDelta(t, {{ .itemType }}(4), ms.At(0), 0.01)
assert.InDelta(t, {{ .itemType }}(2), ms.At(1), 0.01)
{{- else }}
assert.Equal(t, {{ .itemType }}(4), ms.At(0))
assert.Equal(t, {{ .itemType }}(2), ms.At(1))
{{- end }}
}

func Test{{ .structName }}CollapseOffset(t *testing.T) {
ms := New{{ .structName }}()
ms.FromRaw([]{{ .itemType }}{1, 1, 1, 1, 1, 1})

ms.Collapse(4, 3)

assert.Equal(t, 3, ms.Len())
{{- if eq .itemType "float64" }}
assert.InDelta(t, {{ .itemType }}(1), ms.At(0), 0.01)
assert.InDelta(t, {{ .itemType }}(4), ms.At(1), 0.01)
assert.InDelta(t, {{ .itemType }}(1), ms.At(2), 0.01)
{{- else }}
assert.Equal(t, {{ .itemType }}(1), ms.At(0))
assert.Equal(t, {{ .itemType }}(4), ms.At(1))
assert.Equal(t, {{ .itemType }}(1), ms.At(2))
{{- end }}
}
{{- end }}
58 changes: 58 additions & 0 deletions pdata/pcommon/generated_byteslice.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions pdata/pcommon/generated_byteslice_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 58 additions & 0 deletions pdata/pcommon/generated_float64slice.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions pdata/pcommon/generated_float64slice_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading