Skip to content

Commit 2c425f4

Browse files
authored
Merge pull request moby#5067 from tonistiigi/dockerfile-mem-cleanup
dockerfile: cleanup of memory allocations
2 parents d7646bd + 6737deb commit 2c425f4

File tree

33 files changed

+811
-320
lines changed

33 files changed

+811
-320
lines changed

client/llb/meta.go

Lines changed: 66 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"fmt"
66
"net"
77
"path"
8+
"slices"
9+
"sync"
810

911
"github.com/containerd/containerd/platforms"
1012
"github.com/google/shlex"
@@ -111,16 +113,16 @@ func Reset(other State) StateOption {
111113
}
112114
}
113115

114-
func getEnv(s State) func(context.Context, *Constraints) (EnvList, error) {
115-
return func(ctx context.Context, c *Constraints) (EnvList, error) {
116+
func getEnv(s State) func(context.Context, *Constraints) (*EnvList, error) {
117+
return func(ctx context.Context, c *Constraints) (*EnvList, error) {
116118
v, err := s.getValue(keyEnv)(ctx, c)
117119
if err != nil {
118120
return nil, err
119121
}
120122
if v != nil {
121-
return v.(EnvList), nil
123+
return v.(*EnvList), nil
122124
}
123-
return EnvList{}, nil
125+
return &EnvList{}, nil
124126
}
125127
}
126128

@@ -346,54 +348,83 @@ func getSecurity(s State) func(context.Context, *Constraints) (pb.SecurityMode,
346348
}
347349
}
348350

349-
type EnvList []KeyValue
350-
351-
type KeyValue struct {
352-
key string
353-
value string
351+
type EnvList struct {
352+
parent *EnvList
353+
key string
354+
value string
355+
del bool
356+
once sync.Once
357+
l int
358+
values map[string]string
359+
keys []string
354360
}
355361

356-
func (e EnvList) AddOrReplace(k, v string) EnvList {
357-
e = e.Delete(k)
358-
e = append(e, KeyValue{key: k, value: v})
359-
return e
362+
func (e *EnvList) AddOrReplace(k, v string) *EnvList {
363+
return &EnvList{
364+
parent: e,
365+
key: k,
366+
value: v,
367+
l: e.l + 1,
368+
}
360369
}
361370

362-
func (e EnvList) SetDefault(k, v string) EnvList {
371+
func (e *EnvList) SetDefault(k, v string) *EnvList {
363372
if _, ok := e.Get(k); !ok {
364-
e = append(e, KeyValue{key: k, value: v})
373+
return e.AddOrReplace(k, v)
365374
}
366375
return e
367376
}
368377

369-
func (e EnvList) Delete(k string) EnvList {
370-
e = append([]KeyValue(nil), e...)
371-
if i, ok := e.Index(k); ok {
372-
return append(e[:i], e[i+1:]...)
378+
func (e *EnvList) Delete(k string) EnvList {
379+
return EnvList{
380+
parent: e,
381+
key: k,
382+
del: true,
383+
l: e.l + 1,
373384
}
374-
return e
375385
}
376386

377-
func (e EnvList) Get(k string) (string, bool) {
378-
if index, ok := e.Index(k); ok {
379-
return e[index].value, true
380-
}
381-
return "", false
387+
func (e *EnvList) makeValues() {
388+
m := make(map[string]string, e.l)
389+
seen := make(map[string]struct{}, e.l)
390+
keys := make([]string, 0, e.l)
391+
e.keys = e.addValue(keys, m, seen)
392+
e.values = m
393+
slices.Reverse(e.keys)
382394
}
383395

384-
func (e EnvList) Index(k string) (int, bool) {
385-
for i, kv := range e {
386-
if kv.key == k {
387-
return i, true
388-
}
396+
func (e *EnvList) addValue(keys []string, vals map[string]string, seen map[string]struct{}) []string {
397+
if e.parent == nil {
398+
return keys
389399
}
390-
return -1, false
400+
if _, ok := seen[e.key]; !e.del && !ok {
401+
vals[e.key] = e.value
402+
keys = append(keys, e.key)
403+
}
404+
seen[e.key] = struct{}{}
405+
if e.parent != nil {
406+
keys = e.parent.addValue(keys, vals, seen)
407+
}
408+
return keys
409+
}
410+
411+
func (e *EnvList) Get(k string) (string, bool) {
412+
e.once.Do(e.makeValues)
413+
v, ok := e.values[k]
414+
return v, ok
415+
}
416+
417+
func (e *EnvList) Keys() []string {
418+
e.once.Do(e.makeValues)
419+
return e.keys
391420
}
392421

393-
func (e EnvList) ToArray() []string {
394-
out := make([]string, 0, len(e))
395-
for _, kv := range e {
396-
out = append(out, kv.key+"="+kv.value)
422+
func (e *EnvList) ToArray() []string {
423+
keys := e.Keys()
424+
out := make([]string, 0, len(keys))
425+
for _, k := range keys {
426+
v, _ := e.Get(k)
427+
out = append(out, k+"="+v)
397428
}
398429
return out
399430
}

client/llb/state.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -351,16 +351,12 @@ func (s State) GetEnv(ctx context.Context, key string, co ...ConstraintsOpt) (st
351351

352352
// Env returns a new [State] with the provided environment variable set.
353353
// See [Env]
354-
func (s State) Env(ctx context.Context, co ...ConstraintsOpt) ([]string, error) {
354+
func (s State) Env(ctx context.Context, co ...ConstraintsOpt) (*EnvList, error) {
355355
c := &Constraints{}
356356
for _, f := range co {
357357
f.SetConstraintsOption(c)
358358
}
359-
env, err := getEnv(s)(ctx, c)
360-
if err != nil {
361-
return nil, err
362-
}
363-
return env.ToArray(), nil
359+
return getEnv(s)(ctx, c)
364360
}
365361

366362
// GetDir returns the current working directory for the state.

cmd/buildctl/build/exportcache.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
package build
22

33
import (
4-
"encoding/csv"
54
"strings"
65

76
"github.com/moby/buildkit/client"
87
"github.com/moby/buildkit/util/bklog"
98
"github.com/pkg/errors"
9+
"github.com/tonistiigi/go-csvvalue"
1010
)
1111

1212
func parseExportCacheCSV(s string) (client.CacheOptionsEntry, error) {
1313
ex := client.CacheOptionsEntry{
1414
Type: "",
1515
Attrs: map[string]string{},
1616
}
17-
csvReader := csv.NewReader(strings.NewReader(s))
18-
fields, err := csvReader.Read()
17+
fields, err := csvvalue.Fields(s, nil)
1918
if err != nil {
2019
return ex, err
2120
}

cmd/buildctl/build/importcache.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
package build
22

33
import (
4-
"encoding/csv"
54
"strings"
65

76
"github.com/moby/buildkit/client"
87
"github.com/moby/buildkit/util/bklog"
98
"github.com/pkg/errors"
9+
"github.com/tonistiigi/go-csvvalue"
1010
)
1111

1212
func parseImportCacheCSV(s string) (client.CacheOptionsEntry, error) {
1313
im := client.CacheOptionsEntry{
1414
Type: "",
1515
Attrs: map[string]string{},
1616
}
17-
csvReader := csv.NewReader(strings.NewReader(s))
18-
fields, err := csvReader.Read()
17+
fields, err := csvvalue.Fields(s, nil)
1918
if err != nil {
2019
return im, err
2120
}

cmd/buildctl/build/output.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package build
22

33
import (
4-
"encoding/csv"
54
"io"
65
"os"
76
"strconv"
@@ -11,6 +10,7 @@ import (
1110
"github.com/moby/buildkit/client"
1211
"github.com/moby/buildkit/session/filesync"
1312
"github.com/pkg/errors"
13+
"github.com/tonistiigi/go-csvvalue"
1414
)
1515

1616
// parseOutputCSV parses a single --output CSV string
@@ -19,8 +19,7 @@ func parseOutputCSV(s string) (client.ExportEntry, error) {
1919
Type: "",
2020
Attrs: map[string]string{},
2121
}
22-
csvReader := csv.NewReader(strings.NewReader(s))
23-
fields, err := csvReader.Read()
22+
fields, err := csvvalue.Fields(s, nil)
2423
if err != nil {
2524
return ex, err
2625
}

cmd/buildctl/build/registryauthtlscontext.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package build
22

33
import (
4-
"encoding/csv"
54
"strconv"
65
"strings"
76

87
"github.com/moby/buildkit/session/auth/authprovider"
98
"github.com/pkg/errors"
9+
"github.com/tonistiigi/go-csvvalue"
1010
)
1111

1212
type authTLSContextEntry struct {
@@ -19,8 +19,7 @@ type authTLSContextEntry struct {
1919

2020
func parseRegistryAuthTLSContextCSV(s string) (authTLSContextEntry, error) {
2121
authTLSContext := authTLSContextEntry{}
22-
csvReader := csv.NewReader(strings.NewReader(s))
23-
fields, err := csvReader.Read()
22+
fields, err := csvvalue.Fields(s, nil)
2423
if err != nil {
2524
return authTLSContext, err
2625
}

cmd/buildctl/build/secret.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package build
22

33
import (
4-
"encoding/csv"
54
"strings"
65

76
"github.com/moby/buildkit/session"
87
"github.com/moby/buildkit/session/secrets/secretsprovider"
98
"github.com/pkg/errors"
9+
"github.com/tonistiigi/go-csvvalue"
1010
)
1111

1212
// ParseSecret parses --secret
@@ -27,8 +27,7 @@ func ParseSecret(sl []string) (session.Attachable, error) {
2727
}
2828

2929
func parseSecret(val string) (*secretsprovider.Source, error) {
30-
csvReader := csv.NewReader(strings.NewReader(val))
31-
fields, err := csvReader.Read()
30+
fields, err := csvvalue.Fields(val, nil)
3231
if err != nil {
3332
return nil, errors.Wrap(err, "failed to parse csv secret")
3433
}

frontend/attestations/parse.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package attestations
22

33
import (
4-
"encoding/csv"
54
"strings"
65

76
"github.com/pkg/errors"
7+
"github.com/tonistiigi/go-csvvalue"
88
)
99

1010
const (
@@ -63,8 +63,7 @@ func Parse(values map[string]string) (map[string]map[string]string, error) {
6363
if v == "" {
6464
continue
6565
}
66-
csvReader := csv.NewReader(strings.NewReader(v))
67-
fields, err := csvReader.Read()
66+
fields, err := csvvalue.Fields(v, nil)
6867
if err != nil {
6968
return nil, errors.Wrapf(err, "failed to parse %s", k)
7069
}

0 commit comments

Comments
 (0)