diff options
| author | qmuntal <quimmuntal@gmail.com> | 2023-09-27 11:53:30 +0200 |
|---|---|---|
| committer | Quim Muntal <quimmuntal@gmail.com> | 2023-09-28 18:29:48 +0000 |
| commit | 5351bcf8225747f0ef39afc44c0499822992ed11 (patch) | |
| tree | 9bd1b91dab9ecb52f24765af1446ba54c1cc37d9 /src/syscall/exec_windows.go | |
| parent | 6e866fea2b80b0c4744517ab306dfbc47e649144 (diff) | |
| download | go-5351bcf8225747f0ef39afc44c0499822992ed11.tar.xz | |
syscall: simplify and optimize environment block creation on Windows
createEnvBlock currently allocates multiple times: at least one to
convert the slice of strings into a NULL separated slice of bytes, and
then again to encode it as UTF-16. The logic to do so is also quite
complex.
This CL simplifies the logic by allocating only once by encoding the
slice of strings into UTF-16 directly using utf16.AppendRune.
goos: windows
goarch: amd64
pkg: syscall
cpu: Intel(R) Core(TM) i7-10850H CPU @ 2.70GHz
│ old.txt │ new.txt │
│ sec/op │ sec/op vs base │
CreateEnvBlock-12 37.92µ ± 24% 21.36µ ± 8% -43.66% (p=0.000 n=10)
│ old.txt │ new.txt │
│ B/op │ B/op vs base │
CreateEnvBlock-12 109.12Ki ± 0% 26.62Ki ± 0% -75.60% (p=0.000 n=10)
│ old.txt │ new.txt │
│ allocs/op │ allocs/op vs base │
CreateEnvBlock-12 4.000 ± 0% 1.000 ± 0% -75.00% (p=0.000 n=10)
Change-Id: If35f62c3926b486d5253a9ae23a33b979b2f02c2
Reviewed-on: https://go-review.googlesource.com/c/go/+/531355
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Than McIntosh <thanm@google.com>
Diffstat (limited to 'src/syscall/exec_windows.go')
| -rw-r--r-- | src/syscall/exec_windows.go | 26 |
1 files changed, 12 insertions, 14 deletions
diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go index b311a5c746..1220de4cdf 100644 --- a/src/syscall/exec_windows.go +++ b/src/syscall/exec_windows.go @@ -118,11 +118,11 @@ func makeCmdLine(args []string) string { // terminated strings followed by a nil. // Last bytes are two UCS-2 NULs, or four NUL bytes. // If any string contains a NUL, it returns (nil, EINVAL). -func createEnvBlock(envv []string) (*uint16, error) { +func createEnvBlock(envv []string) ([]uint16, error) { if len(envv) == 0 { - return &utf16.Encode([]rune("\x00\x00"))[0], nil + return utf16.Encode([]rune("\x00\x00")), nil } - length := 0 + var length int for _, s := range envv { if bytealg.IndexByteString(s, 0) != -1 { return nil, EINVAL @@ -131,17 +131,15 @@ func createEnvBlock(envv []string) (*uint16, error) { } length += 1 - b := make([]byte, length) - i := 0 + b := make([]uint16, 0, length) for _, s := range envv { - l := len(s) - copy(b[i:i+l], []byte(s)) - copy(b[i+l:i+l+1], []byte{0}) - i = i + l + 1 + for _, c := range s { + b = utf16.AppendRune(b, c) + } + b = utf16.AppendRune(b, 0) } - copy(b[i:i+1], []byte{0}) - - return &utf16.Encode([]rune(string(b)))[0], nil + b = utf16.AppendRune(b, 0) + return b, nil } func CloseOnExec(fd Handle) { @@ -387,9 +385,9 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle pi := new(ProcessInformation) flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT | _EXTENDED_STARTUPINFO_PRESENT if sys.Token != 0 { - err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, envBlock, dirp, &si.StartupInfo, pi) + err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, &envBlock[0], dirp, &si.StartupInfo, pi) } else { - err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, envBlock, dirp, &si.StartupInfo, pi) + err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, &envBlock[0], dirp, &si.StartupInfo, pi) } if err != nil { return 0, 0, err |
