mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
database/sql: avoiding fmt.Sprintf while scanning, avoid allocs with RawBytes
A user reported heavy contention on fmt's printer cache. Avoid fmt.Sprint. We have to do reflection anyway, and there was already an asString function to use strconv, so use it. This CL also eliminates a redundant allocation + copy when scanning into *[]byte (avoiding the intermediate string) and avoids an extra alloc when assigning to a caller's RawBytes (trying to reuse the caller's memory). Fixes #7086 R=golang-codereviews, nightlyone CC=golang-codereviews https://golang.org/cl/50240044
This commit is contained in:
parent
3b8dfc32b3
commit
258ed3f226
2 changed files with 85 additions and 13 deletions
|
|
@ -279,3 +279,51 @@ func TestValueConverters(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that assigning to RawBytes doesn't allocate (and also works).
|
||||
func TestRawBytesAllocs(t *testing.T) {
|
||||
buf := make(RawBytes, 10)
|
||||
test := func(name string, in interface{}, want string) {
|
||||
if err := convertAssign(&buf, in); err != nil {
|
||||
t.Fatalf("%s: convertAssign = %v", name, err)
|
||||
}
|
||||
match := len(buf) == len(want)
|
||||
if match {
|
||||
for i, b := range buf {
|
||||
if want[i] != b {
|
||||
match = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !match {
|
||||
t.Fatalf("%s: got %q (len %d); want %q (len %d)", name, buf, len(buf), want, len(want))
|
||||
}
|
||||
}
|
||||
n := testing.AllocsPerRun(100, func() {
|
||||
test("uint64", uint64(12345678), "12345678")
|
||||
test("uint32", uint32(1234), "1234")
|
||||
test("uint16", uint16(12), "12")
|
||||
test("uint8", uint8(1), "1")
|
||||
test("uint", uint(123), "123")
|
||||
test("int", int(123), "123")
|
||||
test("int8", int8(1), "1")
|
||||
test("int16", int16(12), "12")
|
||||
test("int32", int32(1234), "1234")
|
||||
test("int64", int64(12345678), "12345678")
|
||||
test("float32", float32(1.5), "1.5")
|
||||
test("float64", float64(64), "64")
|
||||
test("bool", false, "false")
|
||||
})
|
||||
if n > 0.5 {
|
||||
t.Fatalf("allocs = %v; want 0", n)
|
||||
}
|
||||
|
||||
// This one involves a convT2E allocation, string -> interface{}
|
||||
n = testing.AllocsPerRun(100, func() {
|
||||
test("string", "foo", "foo")
|
||||
})
|
||||
if n > 1.5 {
|
||||
t.Fatalf("allocs = %v; want max 1", n)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue