]> Cypherpunks repositories - gostls13.git/commitdiff
syscall: optimize SlicePtrFromStrings
authorJosh Bleecher Snyder <josharian@gmail.com>
Sat, 2 Mar 2019 19:14:46 +0000 (11:14 -0800)
committerJosh Bleecher Snyder <josharian@gmail.com>
Sat, 2 Mar 2019 20:13:13 +0000 (20:13 +0000)
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>
src/syscall/exec_unix.go

index 997ccab07e8f770804825425cf44d74454cab61e..4421c449cffb4d70e702057ab0eb84f282d6914e 100644 (file)
@@ -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
 }