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

aggregator: don't allocate memory if we don't have tags #297

Merged
merged 1 commit into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion statsd/aggregator.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,14 +172,22 @@ func (a *aggregator) flushMetrics() []metric {
return metrics
}

// getContext returns the context for a metric name and tags.
//
// The context is the metric name and tags separated by a separator symbol.
// It is not intended to be used as a metric name but as a unique key to aggregate
func getContext(name string, tags []string) string {
c, _ := getContextAndTags(name, tags)
return c
}

// getContextAndTags returns the context and tags for a metric name and tags.
//
// See getContext for usage for context
// The tags are the tags separated by a separator symbol and can be re-used to pass down to the writer
func getContextAndTags(name string, tags []string) (string, string) {
if len(tags) == 0 {
return name + nameSeparatorSymbol, ""
return name, ""
}
n := len(name) + len(nameSeparatorSymbol) + len(tagSeparatorSymbol)*(len(tags)-1)
for _, s := range tags {
Expand Down
20 changes: 19 additions & 1 deletion statsd/aggregator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ func TestGetContextAndTags(t *testing.T) {
testName: "no tags",
name: "name",
tags: nil,
wantContext: "name:",
wantContext: "name",
wantTags: "",
},
{
Expand All @@ -403,3 +403,21 @@ func TestGetContextAndTags(t *testing.T) {
})
}
}

func BenchmarkGetContext(b *testing.B) {
name := "test.metric"
tags := []string{"tag:tag", "foo:bar"}
for i := 0; i < b.N; i++ {
getContext(name, tags)
}
b.ReportAllocs()
}

func BenchmarkGetContextNoTags(b *testing.B) {
name := "test.metric"
var tags []string
for i := 0; i < b.N; i++ {
getContext(name, tags)
}
b.ReportAllocs()
}
16 changes: 13 additions & 3 deletions statsd/statsd_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@ func setupUDSClientServer(b *testing.B, options []statsd.Option) (*statsd.Client
}
go func() {
for {
_, err := conn.Accept()
c, err := conn.Accept()
// We need to read everything from the socket to avoid blocking the sender
buf := make([]byte, 1024)
for {
_, err = c.Read(buf)
if err != nil {
break
}
}
if err != nil {
return
}
Expand Down Expand Up @@ -76,8 +84,9 @@ func benchmarkStatsdDifferentMetrics(b *testing.B, transport string, extraOption
b.RunParallel(func(pb *testing.PB) {
testNumber := atomic.AddInt32(&n, 1)
name := fmt.Sprintf("test.metric%d", testNumber)
tags := []string{"tag:tag"}
for pb.Next() {
client.Gauge(name, 1, []string{"tag:tag"}, 1)
client.Gauge(name, 1, tags, 1)
}
})
client.Flush()
Expand All @@ -96,7 +105,8 @@ func benchmarkStatsdSameMetrics(b *testing.B, transport string, extraOptions ...

b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
client.Gauge("test.metric", 1, []string{"tag:tag"}, 1)
tags := []string{"tag:tag"}
client.Gauge("test.metric", 1, tags, 1)
}
})
client.Flush()
Expand Down