mirror of
https://github.com/golang/go
synced 2024-11-05 15:56:12 -07:00
internal/telemetry: pack strings efficiently into tags
TagOfString() deconstructs a string into length and data pointer using the unsafe package, and then stores the length into Tag.packed and the pointer into Tag.untyped, which it can do without allocations. Tag.UnpackString can reconstruct a string on access also using the unsafe package to rebuild the string header. This makes tag significantly smaller, which in turn makes things a faster name old time/op new time/op delta /Baseline-8 160ns ± 6% 158ns ± 8% ~ /StdLog-8 7.50µs ± 8% 7.47µs ±20% ~ /LogNoExporter-8 1.13µs ± 7% 1.04µs ± 2% -8.08% /TraceNoExporter-8 3.61µs ±15% 2.96µs ± 5% -18.08% /StatsNoExporter-8 1.65µs ± 7% 1.39µs ± 7% -16.14% /LogNoop-8 4.43µs ±14% 4.05µs ± 7% ~ /TraceNoop-8 10.9µs ± 5% 10.1µs ± 8% ~ /StatsNoop-8 8.08µs ± 3% 7.42µs ±13% ~ /Log-8 16.2µs ±14% 13.4µs ± 3% -17.10% /Trace-8 61.7µs ±22% 53.6µs ± 7% ~ /Stats-8 11.3µs ±10% 9.5µs ± 4% -15.56% name old alloc/op new alloc/op delta /Baseline-8 0.00B 0.00B ~ /StdLog-8 552B ± 0% 552B ± 0% ~ /LogNoExporter-8 0.00B 0.00B ~ /TraceNoExporter-8 3.58kB ± 0% 2.82kB ± 0% -21.43% /StatsNoExporter-8 0.00B 0.00B ~ /LogNoop-8 3.58kB ± 0% 2.82kB ± 0% -21.43% /TraceNoop-8 11.5kB ± 0% 9.2kB ± 0% -20.00% /StatsNoop-8 7.17kB ± 0% 5.63kB ± 0% -21.43% /Log-8 3.58kB ± 0% 2.82kB ± 0% -21.43% /Trace-8 27.9kB ± 0% 23.6kB ± 0% -15.60% /Stats-8 7.17kB ± 0% 5.63kB ± 0% -21.43% name old allocs/op new allocs/op delta /Baseline-8 0.00 0.00 ~ /StdLog-8 30.0 ± 0% 30.0 ± 0% ~ /LogNoExporter-8 0.00 0.00 ~ /TraceNoExporter-8 16.0 ± 0% 16.0 ± 0% ~ /StatsNoExporter-8 0.00 0.00 ~ /LogNoop-8 16.0 ± 0% 16.0 ± 0% ~ /TraceNoop-8 64.0 ± 0% 64.0 ± 0% ~ /StatsNoop-8 32.0 ± 0% 32.0 ± 0% ~ /Log-8 16.0 ± 0% 16.0 ± 0% ~ /Trace-8 384 ± 0% 384 ± 0% ~ /Stats-8 32.0 ± 0% 32.0 ± 0% ~ Change-Id: If5c369f138b60435f1aa74120aa3c1b68baae402 Reviewed-on: https://go-review.googlesource.com/c/tools/+/228234 Run-TryBot: Ian Cottrell <iancottrell@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
This commit is contained in:
parent
be55493b88
commit
18395615f2
@ -7,6 +7,8 @@ package event
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tag holds a key and value pair.
|
// Tag holds a key and value pair.
|
||||||
@ -14,7 +16,6 @@ import (
|
|||||||
type Tag struct {
|
type Tag struct {
|
||||||
key Key
|
key Key
|
||||||
packed uint64
|
packed uint64
|
||||||
str string
|
|
||||||
untyped interface{}
|
untyped interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,13 +83,26 @@ func (t Tag) Unpack64() uint64 { return t.packed }
|
|||||||
// TagOfString creates a new tag from a key and a string.
|
// TagOfString creates a new tag from a key and a string.
|
||||||
// This method is for implementing new key types, tag creation should
|
// This method is for implementing new key types, tag creation should
|
||||||
// normally be done with the Of method of the key.
|
// normally be done with the Of method of the key.
|
||||||
func TagOfString(k Key, v string) Tag { return Tag{key: k, str: v} }
|
func TagOfString(k Key, v string) Tag {
|
||||||
|
hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
|
||||||
|
return Tag{
|
||||||
|
key: k,
|
||||||
|
packed: uint64(hdr.Len),
|
||||||
|
untyped: unsafe.Pointer(hdr.Data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// UnpackString assumes the tag was built using TagOfString and returns the
|
// UnpackString assumes the tag was built using TagOfString and returns the
|
||||||
// value that was passed to that constructor.
|
// value that was passed to that constructor.
|
||||||
// This method is for implementing new key types, for type safety normal
|
// This method is for implementing new key types, for type safety normal
|
||||||
// access should be done with the From method of the key.
|
// access should be done with the From method of the key.
|
||||||
func (t Tag) UnpackString() string { return t.str }
|
func (t Tag) UnpackString() string {
|
||||||
|
var v string
|
||||||
|
hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
|
||||||
|
hdr.Data = uintptr(t.untyped.(unsafe.Pointer))
|
||||||
|
hdr.Len = int(t.packed)
|
||||||
|
return *(*string)(unsafe.Pointer(hdr))
|
||||||
|
}
|
||||||
|
|
||||||
// Valid returns true if the Tag is a valid one (it has a key).
|
// Valid returns true if the Tag is a valid one (it has a key).
|
||||||
func (t Tag) Valid() bool { return t.key != nil }
|
func (t Tag) Valid() bool { return t.key != nil }
|
||||||
|
Loading…
Reference in New Issue
Block a user