From: Josh Bleecher Snyder Date: Sat, 2 Mar 2019 19:14:46 +0000 (-0800) Subject: syscall: optimize SlicePtrFromStrings X-Git-Tag: go1.13beta1~1248 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=06c86e0fc3eec6635fce31b8cd6b988087a8f872;p=gostls13.git 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 TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- diff --git a/src/syscall/exec_unix.go b/src/syscall/exec_unix.go index 997ccab07e..4421c449cf 100644 --- a/src/syscall/exec_unix.go +++ b/src/syscall/exec_unix.go @@ -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 }