Reduce allocations during fingerprinting.
Also, add a test to expose https://github.com/prometheus/client_golang/issues/74 . benchmark old ns/op new ns/op delta BenchmarkMetric 7034 6272 -10.83% benchmark old allocs new allocs delta BenchmarkMetric 52 32 -38.46% benchmark old bytes new bytes delta BenchmarkMetric 1976 1800 -8.91%
This commit is contained in:
parent
3d127c266e
commit
a9bdd32c71
|
@ -22,6 +22,8 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
var separator = []byte{0}
|
||||
|
||||
// A Metric is similar to a LabelSet, but the key difference is that a Metric is
|
||||
// a singleton and refers to one and only one stream of samples.
|
||||
type Metric map[LabelName]LabelValue
|
||||
|
@ -64,23 +66,34 @@ func (m Metric) String() string {
|
|||
|
||||
// Fingerprint returns a Metric's Fingerprint.
|
||||
func (m Metric) Fingerprint() Fingerprint {
|
||||
labelLength := len(m)
|
||||
labelNames := make([]string, 0, labelLength)
|
||||
labelNames := make([]string, 0, len(m))
|
||||
maxLength := 0
|
||||
|
||||
for labelName := range m {
|
||||
for labelName, labelValue := range m {
|
||||
labelNames = append(labelNames, string(labelName))
|
||||
if len(labelName) > maxLength {
|
||||
maxLength = len(labelName)
|
||||
}
|
||||
if len(labelValue) > maxLength {
|
||||
maxLength = len(labelValue)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(labelNames)
|
||||
|
||||
summer := fnv.New64a()
|
||||
buf := make([]byte, maxLength)
|
||||
|
||||
for _, labelName := range labelNames {
|
||||
labelValue := m[LabelName(labelName)]
|
||||
|
||||
summer.Write([]byte(labelName))
|
||||
summer.Write([]byte{0})
|
||||
summer.Write([]byte(labelValue))
|
||||
copy(buf, labelName)
|
||||
summer.Write(buf[:len(labelName)])
|
||||
|
||||
summer.Write(separator)
|
||||
|
||||
copy(buf, labelValue)
|
||||
summer.Write(buf[:len(labelValue)])
|
||||
}
|
||||
|
||||
return Fingerprint(binary.LittleEndian.Uint64(summer.Sum(nil)))
|
||||
|
|
|
@ -38,6 +38,24 @@ func testMetric(t testing.TB) {
|
|||
},
|
||||
fingerprint: 1470933794305433534,
|
||||
},
|
||||
// The following two demonstrate a bug in fingerprinting. They
|
||||
// should not have the same fingerprint with a sane
|
||||
// fingerprinting function. See
|
||||
// https://github.com/prometheus/client_golang/issues/74 .
|
||||
{
|
||||
input: Metric{
|
||||
"a": "bb",
|
||||
"b": "c",
|
||||
},
|
||||
fingerprint: 3734646176939799877,
|
||||
},
|
||||
{
|
||||
input: Metric{
|
||||
"a": "b",
|
||||
"bb": "c",
|
||||
},
|
||||
fingerprint: 3734646176939799877,
|
||||
},
|
||||
}
|
||||
|
||||
for i, scenario := range scenarios {
|
||||
|
|
Loading…
Reference in New Issue