Skip to content

Commit 18f681f

Browse files
authored
Optimize dynparquet.serializeDynamicColumns (#651)
This function is used in a hot path. Benchmark results ``` goos: darwin goarch: amd64 pkg: github.com/polarsignals/frostdb/dynparquet cpu: Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ Serialize-8 480.5n ± ∞ ¹ 314.6n ± ∞ ¹ ~ (p=1.000 n=1) ² ¹ need >= 6 samples for confidence interval at level 0.95 ² need >= 4 samples to detect a difference at alpha level 0.05 │ old.txt │ new.txt │ │ B/op │ B/op vs base │ Serialize-8 248.0 ± ∞ ¹ 120.0 ± ∞ ¹ ~ (p=1.000 n=1) ² ¹ need >= 6 samples for confidence interval at level 0.95 ² need >= 4 samples to detect a difference at alpha level 0.05 │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ Serialize-8 6.000 ± ∞ ¹ 3.000 ± ∞ ¹ ~ (p=1.000 n=1) ² ¹ need >= 6 samples for confidence interval at level 0.95 ² need >= 4 samples to detect a difference at alpha level 0.05 ```
1 parent 963c79e commit 18f681f

File tree

2 files changed

+37
-7
lines changed

2 files changed

+37
-7
lines changed

dynparquet/dynamiccolumns.go

+19-7
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,32 @@ var ErrMalformedDynamicColumns = errors.New("malformed dynamic columns string")
1010

1111
func serializeDynamicColumns(dynamicColumns map[string][]string) string {
1212
names := make([]string, 0, len(dynamicColumns))
13-
for name := range dynamicColumns {
13+
var size int
14+
for name, cols := range dynamicColumns {
1415
names = append(names, name)
16+
size += len(name) +
17+
2 // separators
18+
for i := range cols {
19+
size += len(cols[i]) + 1
20+
}
1521
}
1622
sort.Strings(names)
17-
18-
str := ""
23+
var str strings.Builder
24+
str.Grow(size)
1925
for i, name := range names {
2026
if i != 0 {
21-
str += ";"
27+
str.WriteByte(';')
28+
}
29+
str.WriteString(name)
30+
str.WriteByte(':')
31+
for j := range dynamicColumns[name] {
32+
if j != 0 {
33+
str.WriteByte(',')
34+
}
35+
str.WriteString(dynamicColumns[name][j])
2236
}
23-
str += name + ":" + strings.Join(dynamicColumns[name], ",")
2437
}
25-
26-
return str
38+
return str.String()
2739
}
2840

2941
func deserializeDynamicColumns(columns string) (map[string][]string, error) {

dynparquet/dynamiccolumns_test.go

+18
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,21 @@ func BenchmarkDeserialization(b *testing.B) {
5959
_, _ = deserializeDynamicColumns(input)
6060
}
6161
}
62+
63+
func BenchmarkSerialize(b *testing.B) {
64+
input := map[string][]string{
65+
"labels": {
66+
"container",
67+
"namespace",
68+
"node",
69+
"pod",
70+
},
71+
"pprof_labels": {
72+
"profile_id",
73+
},
74+
}
75+
76+
for i := 0; i < b.N; i++ {
77+
_ = serializeDynamicColumns(input)
78+
}
79+
}

0 commit comments

Comments
 (0)