allocation & perf improvements

This commit is contained in:
Cameron Sparr 2016-11-29 18:06:14 +00:00
parent e5c7a71d8e
commit 6fd7361364
2 changed files with 51 additions and 54 deletions

View File

@ -59,13 +59,34 @@ func New(
mType: thisType, mType: thisType,
} }
m.tags = []byte{} // pre-allocate exact size of the tags slice
taglen := 0
for k, v := range tags { for k, v := range tags {
m.tags = append(m.tags, []byte(","+escaper.Replace(k))...) taglen += 2 + len(escaper.Replace(k)) + len(escaper.Replace(v))
m.tags = append(m.tags, []byte("="+escaper.Replace(v))...)
} }
m.tags = make([]byte, taglen)
i := 0 i := 0
for k, v := range tags {
m.tags[i] = ','
i++
i += copy(m.tags[i:], escaper.Replace(k))
m.tags[i] = '='
i++
i += copy(m.tags[i:], escaper.Replace(v))
}
// pre-allocate capacity of the fields slice
fieldlen := 0
for k, _ := range fields {
// 10 bytes is completely arbitrary, but will at least prevent some
// amount of allocations. There's a small possibility this will create
// slightly more allocations for a metric that has many short fields.
fieldlen += len(k) + 10
}
m.fields = make([]byte, 0, fieldlen)
i = 0
for k, v := range fields { for k, v := range fields {
if i != 0 { if i != 0 {
m.fields = append(m.fields, ',') m.fields = append(m.fields, ',')
@ -138,7 +159,7 @@ func (m *metric) Point() *client.Point {
} }
func (m *metric) String() string { func (m *metric) String() string {
return string(m.Serialize()) return string(m.name) + string(m.tags) + " " + string(m.fields) + " " + string(m.t) + "\n"
} }
func (m *metric) SetAggregate(b bool) { func (m *metric) SetAggregate(b bool) {
@ -154,24 +175,21 @@ func (m *metric) Type() telegraf.ValueType {
} }
func (m *metric) Len() int { func (m *metric) Len() int {
return len(m.name) + len(m.tags) + 1 + len(m.fields) + 1 + len(m.t) + 1 // 3 is for 2 spaces surrounding the fields array + newline at the end.
return len(m.name) + len(m.tags) + len(m.fields) + len(m.t) + 3
} }
func (m *metric) Serialize() []byte { func (m *metric) Serialize() []byte {
tmp := make([]byte, m.Len()) tmp := make([]byte, m.Len())
i := 0 i := 0
copy(tmp[i:], m.name) i += copy(tmp[i:], m.name)
i += len(m.name) i += copy(tmp[i:], m.tags)
copy(tmp[i:], m.tags)
i += len(m.tags)
tmp[i] = ' ' tmp[i] = ' '
i++ i++
copy(tmp[i:], m.fields) i += copy(tmp[i:], m.fields)
i += len(m.fields)
tmp[i] = ' ' tmp[i] = ' '
i++ i++
copy(tmp[i:], m.t) i += copy(tmp[i:], m.t)
i += len(m.t)
tmp[i] = '\n' tmp[i] = '\n'
return tmp return tmp
} }
@ -307,12 +325,15 @@ func (m *metric) UnixNano() int64 {
} }
func (m *metric) SetName(name string) { func (m *metric) SetName(name string) {
m.hashID = 0
m.name = []byte(nameEscaper.Replace(name)) m.name = []byte(nameEscaper.Replace(name))
} }
func (m *metric) SetPrefix(prefix string) { func (m *metric) SetPrefix(prefix string) {
m.hashID = 0
m.name = append([]byte(nameEscaper.Replace(prefix)), m.name...) m.name = append([]byte(nameEscaper.Replace(prefix)), m.name...)
} }
func (m *metric) SetSuffix(suffix string) { func (m *metric) SetSuffix(suffix string) {
m.hashID = 0
m.name = append(m.name, []byte(nameEscaper.Replace(suffix))...) m.name = append(m.name, []byte(nameEscaper.Replace(suffix))...)
} }

View File

@ -36,10 +36,9 @@ func BenchmarkNewMetric(b *testing.B) {
s = string(mt.String()) s = string(mt.String())
} }
func BenchmarkNewMetricAndInspect(b *testing.B) { func BenchmarkTags(b *testing.B) {
var mt telegraf.Metric
for n := 0; n < b.N; n++ { for n := 0; n < b.N; n++ {
mt, _ = New("test_metric", var mt, _ = New("test_metric",
map[string]string{ map[string]string{
"test_tag_1": "tag_value_1", "test_tag_1": "tag_value_1",
"test_tag_2": "tag_value_2", "test_tag_2": "tag_value_2",
@ -52,55 +51,32 @@ func BenchmarkNewMetricAndInspect(b *testing.B) {
}, },
time.Now(), time.Now(),
) )
for k, v := range mt.Fields() {
s = k
I = v
}
}
s = mt.String()
}
func BenchmarkTags(b *testing.B) {
var mt, _ = New("test_metric",
map[string]string{
"test_tag_1": "tag_value_1",
"test_tag_2": "tag_value_2",
"test_tag_3": "tag_value_3",
},
map[string]interface{}{
"string_field": "string",
"int_field": int64(1000),
"float_field": float64(2.1),
},
time.Now(),
)
for n := 0; n < b.N; n++ {
tags = mt.Tags() tags = mt.Tags()
} }
s = fmt.Sprint(tags) s = fmt.Sprint(tags)
} }
func BenchmarkFields(b *testing.B) { func BenchmarkFields(b *testing.B) {
var mt, _ = New("test_metric",
map[string]string{
"test_tag_1": "tag_value_1",
"test_tag_2": "tag_value_2",
"test_tag_3": "tag_value_3",
},
map[string]interface{}{
"string_field": "string",
"int_field": int64(1000),
"float_field": float64(2.1),
},
time.Now(),
)
for n := 0; n < b.N; n++ { for n := 0; n < b.N; n++ {
var mt, _ = New("test_metric",
map[string]string{
"test_tag_1": "tag_value_1",
"test_tag_2": "tag_value_2",
"test_tag_3": "tag_value_3",
},
map[string]interface{}{
"string_field": "string",
"int_field": int64(1000),
"float_field": float64(2.1),
},
time.Now(),
)
fields = mt.Fields() fields = mt.Fields()
} }
s = fmt.Sprint(fields) s = fmt.Sprint(fields)
} }
func BenchmarkSerializeMetric(b *testing.B) { func BenchmarkString(b *testing.B) {
mt, _ := New("test_metric", mt, _ := New("test_metric",
map[string]string{ map[string]string{
"test_tag_1": "tag_value_1", "test_tag_1": "tag_value_1",
@ -121,7 +97,7 @@ func BenchmarkSerializeMetric(b *testing.B) {
s = S s = S
} }
func BenchmarkSerializeMetricBytes(b *testing.B) { func BenchmarkSerialize(b *testing.B) {
mt, _ := New("test_metric", mt, _ := New("test_metric",
map[string]string{ map[string]string{
"test_tag_1": "tag_value_1", "test_tag_1": "tag_value_1",