mirror of
https://github.com/golang/go
synced 2024-11-26 02:57:57 -07:00
strings: make use of sizeclasses in (*Builder).Grow
Fixes #64833
Change-Id: Ice3f5dfab65f5525bc7a6f57ddeaabda8d64dfa3
GitHub-Last-Rev: 38f1d6c19d
GitHub-Pull-Request: golang/go#64835
Reviewed-on: https://go-review.googlesource.com/c/go/+/552135
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
cf52e70997
commit
968b71bce4
@ -525,7 +525,7 @@ func Join(s [][]byte, sep []byte) []byte {
|
||||
n += len(v)
|
||||
}
|
||||
|
||||
b := bytealg.MakeNoZero(n)
|
||||
b := bytealg.MakeNoZero(n)[:n:n]
|
||||
bp := copy(b, s[0])
|
||||
for _, v := range s[1:] {
|
||||
bp += copy(b[bp:], sep)
|
||||
@ -610,7 +610,7 @@ func Repeat(b []byte, count int) []byte {
|
||||
chunkMax = len(b)
|
||||
}
|
||||
}
|
||||
nb := bytealg.MakeNoZero(n)
|
||||
nb := bytealg.MakeNoZero(n)[:n:n]
|
||||
bp := copy(nb, b)
|
||||
for bp < n {
|
||||
chunk := bp
|
||||
@ -640,7 +640,7 @@ func ToUpper(s []byte) []byte {
|
||||
// Just return a copy.
|
||||
return append([]byte(""), s...)
|
||||
}
|
||||
b := bytealg.MakeNoZero(len(s))
|
||||
b := bytealg.MakeNoZero(len(s))[:len(s):len(s)]
|
||||
for i := 0; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if 'a' <= c && c <= 'z' {
|
||||
@ -670,7 +670,7 @@ func ToLower(s []byte) []byte {
|
||||
if !hasUpper {
|
||||
return append([]byte(""), s...)
|
||||
}
|
||||
b := bytealg.MakeNoZero(len(s))
|
||||
b := bytealg.MakeNoZero(len(s))[:len(s):len(s)]
|
||||
for i := 0; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if 'A' <= c && c <= 'Z' {
|
||||
|
@ -111,7 +111,8 @@ func LastIndexRabinKarp[T string | []byte](s, sep T) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
// MakeNoZero makes a slice of length and capacity n without zeroing the bytes.
|
||||
// MakeNoZero makes a slice of length n and capacity of at least n Bytes
|
||||
// without zeroing the bytes (including the bytes between len and cap).
|
||||
// It is the caller's responsibility to ensure uninitialized bytes
|
||||
// do not leak to the end user.
|
||||
func MakeNoZero(n int) []byte
|
||||
|
@ -366,5 +366,6 @@ func bytealg_MakeNoZero(len int) []byte {
|
||||
if uintptr(len) > maxAlloc {
|
||||
panicmakeslicelen()
|
||||
}
|
||||
return unsafe.Slice((*byte)(mallocgc(uintptr(len), nil, false)), len)
|
||||
cap := roundupsize(uintptr(len), true)
|
||||
return unsafe.Slice((*byte)(mallocgc(uintptr(cap), nil, false)), cap)[:len]
|
||||
}
|
||||
|
@ -15,7 +15,11 @@ import (
|
||||
// Do not copy a non-zero Builder.
|
||||
type Builder struct {
|
||||
addr *Builder // of receiver, to detect copies by value
|
||||
buf []byte
|
||||
|
||||
// External users should never get direct access to this buffer, since
|
||||
// the slice at some point will be converted to a string using unsafe, also
|
||||
// data between len(buf) and cap(buf) might be uninitialized.
|
||||
buf []byte
|
||||
}
|
||||
|
||||
// noescape hides a pointer from escape analysis. It is the identity function
|
||||
|
@ -385,3 +385,16 @@ func BenchmarkBuildString_ByteBuffer(b *testing.B) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestBuilderGrowSizeclasses(t *testing.T) {
|
||||
s := Repeat("a", 19)
|
||||
allocs := testing.AllocsPerRun(100, func() {
|
||||
var b Builder
|
||||
b.Grow(18)
|
||||
b.WriteString(s)
|
||||
_ = b.String()
|
||||
})
|
||||
if allocs > 1 {
|
||||
t.Fatalf("unexpected amount of allocations: %v, want: 1", allocs)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user