Skip to content

Commit a11b7a1

Browse files
committed
service/s3/s3manager: Use sync.Pool for reuse of part buffers for streaming payloads
1 parent eff3d22 commit a11b7a1

File tree

2 files changed

+19
-18
lines changed

2 files changed

+19
-18
lines changed

CHANGELOG_PENDING.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ SDK Enhancements
2929
* Related to [aws/aws-sdk-go#2310](https://github.com/aws/aws-sdk-go/pull/2310)
3030
* Fixes [#251](https://github.com/aws/aws-sdk-go-v2/issues/251)
3131
* `aws/request` : Retryer is now a named field on Request. ([#393](https://github.com/aws/aws-sdk-go-v2/pull/393))
32-
32+
* `service/s3/s3manager`: Adds a `sync.Pool` to Uploader for reuse of part `[]byte` when uploading streaming body payloads
33+
* Fixes [#402](https://github.com/aws/aws-sdk-go-v2/issues/402)
34+
3335
SDK Bugs
3436
---

service/s3/s3manager/upload.go

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,12 @@ type Uploader struct {
179179
// u.PartSize = 64 * 1024 * 1024 // 64MB per part
180180
// })
181181
func NewUploader(cfg aws.Config, options ...func(*Uploader)) *Uploader {
182+
return newUploader(s3.New(cfg), options...)
183+
}
184+
185+
func newUploader(client s3iface.ClientAPI, options ...func(*Uploader)) *Uploader {
182186
u := &Uploader{
183-
S3: s3.New(cfg),
187+
S3: client,
184188
PartSize: DefaultUploadPartSize,
185189
Concurrency: DefaultUploadConcurrency,
186190
LeavePartsOnError: false,
@@ -214,20 +218,7 @@ func NewUploader(cfg aws.Config, options ...func(*Uploader)) *Uploader {
214218
// u.PartSize = 64 * 1024 * 1024 // 64MB per part
215219
// })
216220
func NewUploaderWithClient(svc s3iface.ClientAPI, options ...func(*Uploader)) *Uploader {
217-
u := &Uploader{
218-
S3: svc,
219-
PartSize: DefaultUploadPartSize,
220-
Concurrency: DefaultUploadConcurrency,
221-
LeavePartsOnError: false,
222-
MaxUploadParts: MaxUploadParts,
223-
BufferProvider: defaultUploadBufferProvider(),
224-
}
225-
226-
for _, option := range options {
227-
option(u)
228-
}
229-
230-
return u
221+
return newUploader(svc, options...)
231222
}
232223

233224
// Upload uploads an object to S3, intelligently buffering large files into
@@ -356,6 +347,8 @@ type uploader struct {
356347

357348
readerPos int64 // current reader position
358349
totalSize int64 // set to -1 if the size is not known
350+
351+
bufferPool sync.Pool
359352
}
360353

361354
// internal logic for deciding whether to upload a single part or use a
@@ -392,6 +385,10 @@ func (u *uploader) init() error {
392385
u.cfg.PartSize = DefaultUploadPartSize
393386
}
394387

388+
u.bufferPool = sync.Pool{
389+
New: func() interface{} { return make([]byte, u.cfg.PartSize) },
390+
}
391+
395392
// Try to get the total size for some optimizations
396393
return u.initSize()
397394
}
@@ -460,11 +457,13 @@ func (u *uploader) nextReader() (io.ReadSeeker, int, func(), error) {
460457
return reader, int(n), cleanup, err
461458

462459
default:
463-
part := make([]byte, u.cfg.PartSize)
460+
part := u.bufferPool.Get().([]byte)
464461
n, err := readFillBuf(r, part)
465462
u.readerPos += int64(n)
466463

467-
cleanup := func() {}
464+
cleanup := func() {
465+
u.bufferPool.Put(part)
466+
}
468467

469468
return bytes.NewReader(part[0:n]), n, cleanup, err
470469
}

0 commit comments

Comments
 (0)