mirror of
https://github.com/golang/go
synced 2024-11-19 13:04:45 -07:00
runtime: simplify memory capacity check in growslice
Instead of comparing if the number of elements will not fit into memory check if the memory size of the slices backing memory is higher then the memory limit. This avoids a division or maxElems lookup. With et.size > 0: uintptr(newcap) > maxSliceCap(et.size) -> uintptr(int(capmem / et.size)) > _MaxMem / et.size -> capmem / et.size > _MaxMem / et.size -> capmem > _MaxMem Note that due to integer division from capmem > _MaxMem it does not follow that uintptr(newcap) > maxSliceCap(et.size). Consolidated runtime GrowSlice benchmarks by using sub-benchmarks and added more struct sizes to show performance improvement when division is avoided for element sizes larger than 32 bytes. AMD64: GrowSlice/Byte 38.9ns ± 2% 38.9ns ± 1% ~ (p=0.974 n=20+20) GrowSlice/Int 58.3ns ± 3% 58.0ns ± 2% ~ (p=0.154 n=20+19) GrowSlice/Ptr 95.7ns ± 2% 95.1ns ± 2% -0.60% (p=0.034 n=20+20) GrowSlice/Struct/24 95.4ns ± 1% 93.9ns ± 1% -1.54% (p=0.000 n=19+19) GrowSlice/Struct/32 110ns ± 1% 108ns ± 1% -1.76% (p=0.000 n=19+20) GrowSlice/Struct/40 138ns ± 1% 128ns ± 1% -7.09% (p=0.000 n=20+20) Change-Id: I1c37857c74ea809da373e668791caffb6a5cbbd3 Reviewed-on: https://go-review.googlesource.com/53471 Run-TryBot: Martin Möhrmann <moehrmann@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
ef6978b218
commit
365594ad59
@ -18,42 +18,52 @@ func BenchmarkMakeSlice(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGrowSliceBytes(b *testing.B) {
|
||||
b.StopTimer()
|
||||
var x = make([]byte, 9)
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = append([]byte(nil), x...)
|
||||
}
|
||||
}
|
||||
type (
|
||||
struct24 struct{ a, b, c int64 }
|
||||
struct32 struct{ a, b, c, d int64 }
|
||||
struct40 struct{ a, b, c, d, e int64 }
|
||||
)
|
||||
|
||||
func BenchmarkGrowSliceInts(b *testing.B) {
|
||||
b.StopTimer()
|
||||
var x = make([]int, 9)
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = append([]int(nil), x...)
|
||||
}
|
||||
}
|
||||
func BenchmarkGrowSlice(b *testing.B) {
|
||||
b.Run("Byte", func(b *testing.B) {
|
||||
x := make([]byte, 9)
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = append([]byte(nil), x...)
|
||||
}
|
||||
})
|
||||
b.Run("Int", func(b *testing.B) {
|
||||
x := make([]int, 9)
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = append([]int(nil), x...)
|
||||
}
|
||||
})
|
||||
b.Run("Ptr", func(b *testing.B) {
|
||||
x := make([]*byte, 9)
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = append([]*byte(nil), x...)
|
||||
}
|
||||
})
|
||||
b.Run("Struct", func(b *testing.B) {
|
||||
b.Run("24", func(b *testing.B) {
|
||||
x := make([]struct24, 9)
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = append([]struct24(nil), x...)
|
||||
}
|
||||
})
|
||||
b.Run("32", func(b *testing.B) {
|
||||
x := make([]struct32, 9)
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = append([]struct32(nil), x...)
|
||||
}
|
||||
})
|
||||
b.Run("40", func(b *testing.B) {
|
||||
x := make([]struct40, 9)
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = append([]struct40(nil), x...)
|
||||
}
|
||||
})
|
||||
|
||||
func BenchmarkGrowSlicePtr(b *testing.B) {
|
||||
b.StopTimer()
|
||||
var x = make([]*byte, 9)
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = append([]*byte(nil), x...)
|
||||
}
|
||||
}
|
||||
|
||||
type struct24 struct{ a, b, c int64 }
|
||||
|
||||
func BenchmarkGrowSliceStruct24Bytes(b *testing.B) {
|
||||
b.StopTimer()
|
||||
var x = make([]struct24, 9)
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = append([]struct24(nil), x...)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkAppend(b *testing.B) {
|
||||
|
@ -131,7 +131,7 @@ func growslice(et *_type, old slice, cap int) slice {
|
||||
newcap = int(capmem / et.size)
|
||||
}
|
||||
|
||||
if cap < old.cap || uintptr(newcap) > maxSliceCap(et.size) {
|
||||
if cap < old.cap || capmem > _MaxMem {
|
||||
panic(errorString("growslice: cap out of range"))
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user