1
0
mirror of https://github.com/golang/go synced 2024-11-23 17:50:06 -07:00

os: allocate buffer lazily in Expand

As an example of why this might happen,
consider this code from cmd/internal/objfile:

// Expand literal "$GOROOT" rewritten by obj.AbsFile()
filename = filepath.Clean(os.ExpandEnv(filename))

In this case, filename might not contain "$GOROOT",
in which case we can skip the buffer entirely.

name               old time/op    new time/op    delta
Expand/noop-8        46.7ns ± 1%    12.9ns ± 1%   -72.47%  (p=0.000 n=9+9)
Expand/multiple-8     139ns ± 1%     137ns ± 1%    -1.36%  (p=0.001 n=10+10)

The Expand/multiple improvement is probably noise.

This speeds up cmd/objdump detectably, if not much.
Using "benchcmd ObjdumpCompile go tool objdump `go tool -n compile`":

name            old time/op       new time/op       delta
ObjdumpCompile        9.35s ± 2%        9.07s ± 3%  -3.00%  (p=0.000 n=18+18)

Updates #24725

Change-Id: Id31ec6a9b8dfb3c0f1db58fe1f958e11c39e656c
Reviewed-on: https://go-review.googlesource.com/106697
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:
Josh Bleecher Snyder 2018-04-12 12:15:58 -07:00
parent 3cb067d70d
commit 86181120bd

View File

@ -14,11 +14,14 @@ import (
// Expand replaces ${var} or $var in the string based on the mapping function. // Expand replaces ${var} or $var in the string based on the mapping function.
// For example, os.ExpandEnv(s) is equivalent to os.Expand(s, os.Getenv). // For example, os.ExpandEnv(s) is equivalent to os.Expand(s, os.Getenv).
func Expand(s string, mapping func(string) string) string { func Expand(s string, mapping func(string) string) string {
buf := make([]byte, 0, 2*len(s)) var buf []byte
// ${} is all ASCII, so bytes are fine for this operation. // ${} is all ASCII, so bytes are fine for this operation.
i := 0 i := 0
for j := 0; j < len(s); j++ { for j := 0; j < len(s); j++ {
if s[j] == '$' && j+1 < len(s) { if s[j] == '$' && j+1 < len(s) {
if buf == nil {
buf = make([]byte, 0, 2*len(s))
}
buf = append(buf, s[i:j]...) buf = append(buf, s[i:j]...)
name, w := getShellName(s[j+1:]) name, w := getShellName(s[j+1:])
// If the name is empty, keep the $. // If the name is empty, keep the $.
@ -31,6 +34,9 @@ func Expand(s string, mapping func(string) string) string {
i = j + 1 i = j + 1
} }
} }
if buf == nil {
return s
}
return string(buf) + s[i:] return string(buf) + s[i:]
} }