Skip to content

Commit 70f5497

Browse files
committed
Merge pull request #75 from prometheus/beorn7/timestamp
Reduce allocations during fingerprinting.
2 parents 3d6b23a + a9bdd32 commit 70f5497

File tree

2 files changed

+37
-6
lines changed

2 files changed

+37
-6
lines changed

model/metric.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"strings"
2323
)
2424

25+
var separator = []byte{0}
26+
2527
// A Metric is similar to a LabelSet, but the key difference is that a Metric is
2628
// a singleton and refers to one and only one stream of samples.
2729
type Metric map[LabelName]LabelValue
@@ -64,23 +66,34 @@ func (m Metric) String() string {
6466

6567
// Fingerprint returns a Metric's Fingerprint.
6668
func (m Metric) Fingerprint() Fingerprint {
67-
labelLength := len(m)
68-
labelNames := make([]string, 0, labelLength)
69+
labelNames := make([]string, 0, len(m))
70+
maxLength := 0
6971

70-
for labelName := range m {
72+
for labelName, labelValue := range m {
7173
labelNames = append(labelNames, string(labelName))
74+
if len(labelName) > maxLength {
75+
maxLength = len(labelName)
76+
}
77+
if len(labelValue) > maxLength {
78+
maxLength = len(labelValue)
79+
}
7280
}
7381

7482
sort.Strings(labelNames)
7583

7684
summer := fnv.New64a()
85+
buf := make([]byte, maxLength)
7786

7887
for _, labelName := range labelNames {
7988
labelValue := m[LabelName(labelName)]
8089

81-
summer.Write([]byte(labelName))
82-
summer.Write([]byte{0})
83-
summer.Write([]byte(labelValue))
90+
copy(buf, labelName)
91+
summer.Write(buf[:len(labelName)])
92+
93+
summer.Write(separator)
94+
95+
copy(buf, labelValue)
96+
summer.Write(buf[:len(labelValue)])
8497
}
8598

8699
return Fingerprint(binary.LittleEndian.Uint64(summer.Sum(nil)))

model/metric_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,24 @@ func testMetric(t testing.TB) {
3838
},
3939
fingerprint: 1470933794305433534,
4040
},
41+
// The following two demonstrate a bug in fingerprinting. They
42+
// should not have the same fingerprint with a sane
43+
// fingerprinting function. See
44+
// https://github.com/prometheus/client_golang/issues/74 .
45+
{
46+
input: Metric{
47+
"a": "bb",
48+
"b": "c",
49+
},
50+
fingerprint: 3734646176939799877,
51+
},
52+
{
53+
input: Metric{
54+
"a": "b",
55+
"bb": "c",
56+
},
57+
fingerprint: 3734646176939799877,
58+
},
4159
}
4260

4361
for i, scenario := range scenarios {

0 commit comments

Comments
 (0)