moby/container/env.go
Brian Goff 5702a89db6 Use strings.Index instead of strings.Split
Since we don't need the actual split values, instead of calling
`strings.Split`, which allocates new slices on each call, use
`strings.Index`.

This significantly reduces the allocations required when doing env value
replacements.
Additionally, pre-allocate the env var slice, even if we allocate a
little more than we need, it keeps us from having to do multiple
allocations while appending.

```
benchmark                                     old ns/op     new ns/op     delta
BenchmarkReplaceOrAppendEnvValues/0-8         486           313           -35.60%
BenchmarkReplaceOrAppendEnvValues/100-8       10553         1535          -85.45%
BenchmarkReplaceOrAppendEnvValues/1000-8      94275         12758         -86.47%
BenchmarkReplaceOrAppendEnvValues/10000-8     1161268       129269        -88.87%

benchmark                                     old allocs     new allocs     delta
BenchmarkReplaceOrAppendEnvValues/0-8         5              2              -60.00%
BenchmarkReplaceOrAppendEnvValues/100-8       110            0              -100.00%
BenchmarkReplaceOrAppendEnvValues/1000-8      1013           0              -100.00%
BenchmarkReplaceOrAppendEnvValues/10000-8     10022          0              -100.00%

benchmark                                     old bytes     new bytes     delta
BenchmarkReplaceOrAppendEnvValues/0-8         192           24            -87.50%
BenchmarkReplaceOrAppendEnvValues/100-8       7360          0             -100.00%
BenchmarkReplaceOrAppendEnvValues/1000-8      64832         0             -100.00%
BenchmarkReplaceOrAppendEnvValues/10000-8     1146049       0             -100.00%
```

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2020-04-24 11:10:13 -07:00

43 lines
1 KiB
Go

package container // import "github.com/docker/docker/container"
import (
"strings"
)
// ReplaceOrAppendEnvValues returns the defaults with the overrides either
// replaced by env key or appended to the list
func ReplaceOrAppendEnvValues(defaults, overrides []string) []string {
cache := make(map[string]int, len(defaults))
for i, e := range defaults {
index := strings.Index(e, "=")
cache[e[:index]] = i
}
for _, value := range overrides {
// Values w/o = means they want this env to be removed/unset.
index := strings.Index(value, "=")
if index < 0 {
// no "=" in value
if i, exists := cache[value]; exists {
defaults[i] = "" // Used to indicate it should be removed
}
continue
}
if i, exists := cache[value[:index]]; exists {
defaults[i] = value
} else {
defaults = append(defaults, value)
}
}
// Now remove all entries that we want to "unset"
for i := 0; i < len(defaults); i++ {
if defaults[i] == "" {
defaults = append(defaults[:i], defaults[i+1:]...)
i--
}
}
return defaults
}