mirror of
https://github.com/golang/go
synced 2024-11-05 15:26:15 -07:00
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>
This commit is contained in:
parent
6e866fea2b
commit
5351bcf822
@ -118,11 +118,11 @@ func makeCmdLine(args []string) string {
|
|||||||
// terminated strings followed by a nil.
|
// terminated strings followed by a nil.
|
||||||
// Last bytes are two UCS-2 NULs, or four NUL bytes.
|
// Last bytes are two UCS-2 NULs, or four NUL bytes.
|
||||||
// If any string contains a NUL, it returns (nil, EINVAL).
|
// 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 {
|
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 {
|
for _, s := range envv {
|
||||||
if bytealg.IndexByteString(s, 0) != -1 {
|
if bytealg.IndexByteString(s, 0) != -1 {
|
||||||
return nil, EINVAL
|
return nil, EINVAL
|
||||||
@ -131,17 +131,15 @@ func createEnvBlock(envv []string) (*uint16, error) {
|
|||||||
}
|
}
|
||||||
length += 1
|
length += 1
|
||||||
|
|
||||||
b := make([]byte, length)
|
b := make([]uint16, 0, length)
|
||||||
i := 0
|
|
||||||
for _, s := range envv {
|
for _, s := range envv {
|
||||||
l := len(s)
|
for _, c := range s {
|
||||||
copy(b[i:i+l], []byte(s))
|
b = utf16.AppendRune(b, c)
|
||||||
copy(b[i+l:i+l+1], []byte{0})
|
}
|
||||||
i = i + l + 1
|
b = utf16.AppendRune(b, 0)
|
||||||
}
|
}
|
||||||
copy(b[i:i+1], []byte{0})
|
b = utf16.AppendRune(b, 0)
|
||||||
|
return b, nil
|
||||||
return &utf16.Encode([]rune(string(b)))[0], nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CloseOnExec(fd Handle) {
|
func CloseOnExec(fd Handle) {
|
||||||
@ -387,9 +385,9 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
|
|||||||
pi := new(ProcessInformation)
|
pi := new(ProcessInformation)
|
||||||
flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT | _EXTENDED_STARTUPINFO_PRESENT
|
flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT | _EXTENDED_STARTUPINFO_PRESENT
|
||||||
if sys.Token != 0 {
|
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 {
|
} 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 {
|
if err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
|
Loading…
Reference in New Issue
Block a user