Skip to content

Commit 1df32e3

Browse files
authored
Use sync.Pools for allocations (#1568)
This should help a lot with memory usage when building lots of things in the same process. Signed-off-by: Jon Johnson <[email protected]>
1 parent 98af90c commit 1df32e3

File tree

3 files changed

+93
-22
lines changed

3 files changed

+93
-22
lines changed

pkg/apk/expandapk/expandapk.go

+43-11
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,40 @@ import (
2828
"go.opentelemetry.io/otel"
2929
)
3030

31+
var slicePool = sync.Pool{
32+
New: func() interface{} {
33+
return make([]byte, 1<<20)
34+
},
35+
}
36+
37+
func pooledSlice() []byte {
38+
return slicePool.Get().([]byte)
39+
}
40+
41+
var readerPool = sync.Pool{
42+
New: func() interface{} {
43+
return bufio.NewReaderSize(nil, 1<<20)
44+
},
45+
}
46+
47+
func pooledBufioReader(r io.Reader) *bufio.Reader {
48+
br := readerPool.Get().(*bufio.Reader)
49+
br.Reset(r)
50+
return br
51+
}
52+
53+
var writerPool = sync.Pool{
54+
New: func() interface{} {
55+
return bufio.NewWriterSize(nil, 1<<20)
56+
},
57+
}
58+
59+
func pooledBufioWriter(w io.Writer) *bufio.Writer {
60+
bw := writerPool.Get().(*bufio.Writer)
61+
bw.Reset(w)
62+
return bw
63+
}
64+
3165
// APKExpanded contains information about and reference to an expanded APK package.
3266
// Close() deletes all temporary files and directories created during the expansion process.
3367
type APKExpanded struct {
@@ -66,8 +100,6 @@ type APKExpanded struct {
66100
controlData []byte
67101
}
68102

69-
const meg = 1 << 20
70-
71103
func (a *APKExpanded) ControlData() ([]byte, error) {
72104
a.Lock()
73105
defer a.Unlock()
@@ -100,20 +132,16 @@ func (a *APKExpanded) PackageData() (*os.File, error) {
100132
return nil, fmt.Errorf("opening package data file: %w", err)
101133
}
102134

103-
// Use min(1MB, a.Size) bufio to avoid GC pressure for small packages.
104-
bufSize := meg
105-
if total := int(a.Size); total != 0 && total < bufSize {
106-
bufSize = total
107-
}
108-
109135
// Handle old caches without the uncompressed file.
110136
f, err := os.Open(a.PackageFile)
111137
if err != nil {
112138
return nil, fmt.Errorf("opening %q: %w", a.PackageFile, err)
113139
}
114140
defer f.Close()
115141

116-
br := bufio.NewReaderSize(f, bufSize)
142+
br := pooledBufioReader(f)
143+
defer readerPool.Put(br)
144+
117145
zr, err := gzip.NewReader(br)
118146
if err != nil {
119147
return nil, fmt.Errorf("parsing %q: %w", a.PackageFile, err)
@@ -124,7 +152,9 @@ func (a *APKExpanded) PackageData() (*os.File, error) {
124152
return nil, fmt.Errorf("opening tar file %q: %w", a.TarFile, err)
125153
}
126154

127-
buf := make([]byte, bufSize)
155+
buf := pooledSlice()
156+
defer slicePool.Put(buf)
157+
128158
if _, err := io.CopyBuffer(uf, zr, buf); err != nil {
129159
return nil, fmt.Errorf("decompressing %q: %w", a.PackageFile, err)
130160
}
@@ -390,7 +420,9 @@ func ExpandApk(ctx context.Context, source io.Reader, cacheDir string) (*APKExpa
390420
if err != nil {
391421
return nil, fmt.Errorf("opening tar file: %w", err)
392422
}
393-
bw := bufio.NewWriterSize(tarfile, 1<<20)
423+
bw := pooledBufioWriter(tarfile)
424+
defer writerPool.Put(bw)
425+
394426
tr := io.TeeReader(gzi, bw)
395427

396428
if err := checkSums(ctx, tr); err != nil {

pkg/apk/internal/tarfs/tarfs.go

+18-1
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,22 @@ import (
2424
"io/fs"
2525
"path"
2626
"slices"
27+
"sync"
2728
"time"
2829
)
2930

31+
var readerPool = sync.Pool{
32+
New: func() interface{} {
33+
return bufio.NewReaderSize(nil, 1<<20)
34+
},
35+
}
36+
37+
func pooledBufioReader(r io.Reader) *bufio.Reader {
38+
br := readerPool.Get().(*bufio.Reader)
39+
br.Reset(r)
40+
return br
41+
}
42+
3043
type Entry struct {
3144
Header tar.Header
3245
Offset int64
@@ -204,7 +217,11 @@ func New(ra io.ReaderAt, size int64) (*FS, error) {
204217

205218
// TODO: Consider caching this across builds.
206219
r := io.NewSectionReader(ra, 0, size)
207-
cr := &countReader{bufio.NewReaderSize(r, 1<<20), 0}
220+
221+
br := pooledBufioReader(r)
222+
defer readerPool.Put(br)
223+
224+
cr := &countReader{br, 0}
208225
tr := tar.NewReader(cr)
209226
for {
210227
hdr, err := tr.Next()

pkg/build/build_implementation.go

+32-10
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"os"
2626
"path/filepath"
2727
"runtime"
28+
"sync"
2829

2930
gzip "github.com/klauspost/pgzip"
3031
"github.com/sigstore/cosign/v2/pkg/oci"
@@ -48,12 +49,33 @@ import (
4849
// concurrent builds on giant machines, and uses only 1 core on tiny machines.
4950
var pgzipThreads = min(runtime.GOMAXPROCS(0), 8)
5051

51-
func min(l, r int) int {
52-
if l < r {
53-
return l
54-
}
52+
var pgzipPool = sync.Pool{
53+
New: func() interface{} {
54+
zw := gzip.NewWriter(nil)
55+
if err := zw.SetConcurrency(1<<20, pgzipThreads); err != nil {
56+
// This should never happen.
57+
panic(fmt.Errorf("tried to set pgzip concurrency to %d: %w", pgzipThreads, err))
58+
}
59+
return zw
60+
},
61+
}
62+
63+
func pooledGzipWriter(w io.Writer) *gzip.Writer {
64+
zw := pgzipPool.Get().(*gzip.Writer)
65+
zw.Reset(w)
66+
return zw
67+
}
5568

56-
return r
69+
var bufioPool = sync.Pool{
70+
New: func() interface{} {
71+
return bufio.NewWriterSize(nil, 1<<22)
72+
},
73+
}
74+
75+
func pooledBufioWriter(w io.Writer) *bufio.Writer {
76+
bw := bufioPool.Get().(*bufio.Writer)
77+
bw.Reset(w)
78+
return bw
5779
}
5880

5981
// BuildTarball takes the fully populated working directory and saves it to
@@ -85,11 +107,11 @@ func (bc *Context) BuildTarball(ctx context.Context) (string, hash.Hash, hash.Ha
85107

86108
digest := sha256.New()
87109

88-
buf := bufio.NewWriterSize(outfile, 1<<22)
89-
gzw := gzip.NewWriter(io.MultiWriter(digest, buf))
90-
if err := gzw.SetConcurrency(1<<20, pgzipThreads); err != nil {
91-
return "", nil, nil, 0, fmt.Errorf("tried to set pgzip concurrency to %d: %w", pgzipThreads, err)
92-
}
110+
buf := pooledBufioWriter(outfile)
111+
defer bufioPool.Put(buf)
112+
113+
gzw := pooledGzipWriter(io.MultiWriter(digest, buf))
114+
defer pgzipPool.Put(gzw)
93115

94116
diffid := sha256.New()
95117

0 commit comments

Comments
 (0)