mirror of
https://github.com/golang/go
synced 2024-10-14 11:53:56 +00:00
syscall: optimize SlicePtrFromStrings
Instead of allocating a byte slice for every string, calculated the required size and create a single slice big enough to hold all of them. As an added benefit, any error encountered will now be returned before allocations occur. os/exec package benchmarks: name old time/op new time/op delta ExecEcho-8 2.14ms ± 1% 2.14ms ± 3% ~ (p=0.842 n=10+9) name old alloc/op new alloc/op delta ExecEcho-8 6.35kB ± 0% 6.18kB ± 0% -2.65% (p=0.000 n=10+10) name old allocs/op new allocs/op delta ExecEcho-8 69.0 ± 0% 36.0 ± 0% -47.83% (p=0.000 n=10+10) Change-Id: I84118d8473037d873f73903d4e4f6ed14f531ce7 Reviewed-on: https://go-review.googlesource.com/c/164961 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
beadf433c3
commit
06c86e0fc3
|
@ -9,6 +9,7 @@
|
|||
package syscall
|
||||
|
||||
import (
|
||||
"internal/bytealg"
|
||||
"runtime"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
@ -81,15 +82,21 @@ func StringSlicePtr(ss []string) []*byte {
|
|||
// pointers to NUL-terminated byte arrays. If any string contains
|
||||
// a NUL byte, it returns (nil, EINVAL).
|
||||
func SlicePtrFromStrings(ss []string) ([]*byte, error) {
|
||||
var err error
|
||||
bb := make([]*byte, len(ss)+1)
|
||||
for i := 0; i < len(ss); i++ {
|
||||
bb[i], err = BytePtrFromString(ss[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
n := 0
|
||||
for _, s := range ss {
|
||||
if bytealg.IndexByteString(s, 0) != -1 {
|
||||
return nil, EINVAL
|
||||
}
|
||||
n += len(s) + 1 // +1 for NUL
|
||||
}
|
||||
bb := make([]*byte, len(ss)+1)
|
||||
b := make([]byte, n)
|
||||
n = 0
|
||||
for i, s := range ss {
|
||||
bb[i] = &b[n]
|
||||
copy(b[n:], s)
|
||||
n += len(s) + 1
|
||||
}
|
||||
bb[len(ss)] = nil
|
||||
return bb, nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue