github.com/aavshr/aws-sdk-go@v1.41.3/awstesting/integration/performance/s3UploadManager/main_test.go (about) 1 //go:build integration && perftest 2 // +build integration,perftest 3 4 package main 5 6 import ( 7 "flag" 8 "fmt" 9 "io" 10 "os" 11 "strconv" 12 "strings" 13 "testing" 14 15 "github.com/aavshr/aws-sdk-go/aws" 16 "github.com/aavshr/aws-sdk-go/awstesting" 17 "github.com/aavshr/aws-sdk-go/awstesting/integration" 18 "github.com/aavshr/aws-sdk-go/internal/sdkio" 19 "github.com/aavshr/aws-sdk-go/service/s3/s3manager" 20 ) 21 22 var benchConfig BenchmarkConfig 23 24 type BenchmarkConfig struct { 25 bucket string 26 tempdir string 27 clientConfig ClientConfig 28 sizes string 29 parts string 30 concurrency string 31 bufferSize string 32 } 33 34 func (b *BenchmarkConfig) SetupFlags(prefix string, flagSet *flag.FlagSet) { 35 flagSet.StringVar(&b.bucket, "bucket", "", "Bucket to use for benchmark") 36 flagSet.StringVar(&b.tempdir, "temp", os.TempDir(), "location to create temporary files") 37 38 flagSet.StringVar(&b.sizes, "size", 39 fmt.Sprintf("%d,%d", 40 5*sdkio.MebiByte, 41 1*sdkio.GibiByte), "file sizes to benchmark separated by comma") 42 43 flagSet.StringVar(&b.parts, "part", 44 fmt.Sprintf("%d,%d,%d", 45 s3manager.DefaultUploadPartSize, 46 25*sdkio.MebiByte, 47 100*sdkio.MebiByte), "part sizes to benchmark separated by comma") 48 49 flagSet.StringVar(&b.concurrency, "concurrency", 50 fmt.Sprintf("%d,%d,%d", 51 s3manager.DefaultUploadConcurrency, 52 2*s3manager.DefaultUploadConcurrency, 53 100), 54 "concurrences to benchmark separated comma") 55 56 flagSet.StringVar(&b.bufferSize, "buffer", fmt.Sprintf("%d,%d", 0, 1*sdkio.MebiByte), "part sizes to benchmark separated comma") 57 b.clientConfig.SetupFlags(prefix, flagSet) 58 } 59 60 func (b *BenchmarkConfig) BufferSizes() []int { 61 ints, err := b.stringToInt(b.bufferSize) 62 if err != nil { 63 panic(fmt.Sprintf("failed to parse file sizes: %v", err)) 64 } 65 66 return ints 67 } 68 69 func (b *BenchmarkConfig) FileSizes() []int64 { 70 ints, err := b.stringToInt64(b.sizes) 71 if err != nil { 72 panic(fmt.Sprintf("failed to parse file sizes: %v", err)) 73 } 74 75 return ints 76 } 77 78 func (b *BenchmarkConfig) PartSizes() []int64 { 79 ints, err := b.stringToInt64(b.parts) 80 if err != nil { 81 panic(fmt.Sprintf("failed to parse part sizes: %v", err)) 82 } 83 84 return ints 85 } 86 87 func (b *BenchmarkConfig) Concurrences() []int { 88 ints, err := b.stringToInt(b.concurrency) 89 if err != nil { 90 panic(fmt.Sprintf("failed to parse part sizes: %v", err)) 91 } 92 93 return ints 94 } 95 96 func (b *BenchmarkConfig) stringToInt(s string) ([]int, error) { 97 int64s, err := b.stringToInt64(s) 98 if err != nil { 99 return nil, err 100 } 101 102 var ints []int 103 for i := range int64s { 104 ints = append(ints, int(int64s[i])) 105 } 106 107 return ints, nil 108 } 109 110 func (b *BenchmarkConfig) stringToInt64(s string) ([]int64, error) { 111 var sizes []int64 112 113 split := strings.Split(s, ",") 114 115 for _, size := range split { 116 size = strings.Trim(size, " ") 117 i, err := strconv.ParseInt(size, 10, 64) 118 if err != nil { 119 return nil, fmt.Errorf("invalid integer %s: %v", size, err) 120 } 121 122 sizes = append(sizes, i) 123 } 124 125 return sizes, nil 126 } 127 128 func BenchmarkUpload(b *testing.B) { 129 baseSdkConfig := SDKConfig{WithUnsignedPayload: true} 130 131 for _, fileSize := range benchConfig.FileSizes() { 132 b.Run(fmt.Sprintf("%s File", integration.SizeToName(int(fileSize))), func(b *testing.B) { 133 for _, concurrency := range benchConfig.Concurrences() { 134 b.Run(fmt.Sprintf("%d Concurrency", concurrency), func(b *testing.B) { 135 for _, partSize := range benchConfig.PartSizes() { 136 if partSize > fileSize { 137 continue 138 } 139 partSize = getUploadPartSize(fileSize, partSize) 140 b.Run(fmt.Sprintf("%s PartSize", integration.SizeToName(int(partSize))), func(b *testing.B) { 141 for _, bufferSize := range benchConfig.BufferSizes() { 142 var name string 143 if bufferSize == 0 { 144 name = "Unbuffered" 145 } else { 146 name = fmt.Sprintf("%s Buffer", integration.SizeToName(bufferSize)) 147 } 148 b.Run(name, func(b *testing.B) { 149 sdkConfig := baseSdkConfig 150 151 sdkConfig.Concurrency = concurrency 152 sdkConfig.PartSize = partSize 153 if bufferSize > 0 { 154 sdkConfig.BufferProvider = s3manager.NewBufferedReadSeekerWriteToPool(bufferSize) 155 } 156 157 for i := 0; i < b.N; i++ { 158 for { 159 b.ResetTimer() 160 reader := aws.ReadSeekCloser(io.LimitReader(&awstesting.EndlessReader{}, fileSize)) 161 err := benchUpload(b, benchConfig.bucket, integration.UniqueID(), reader, sdkConfig, benchConfig.clientConfig) 162 if err != nil { 163 b.Logf("upload failed, retrying: %v", err) 164 continue 165 } 166 break 167 } 168 } 169 }) 170 } 171 }) 172 } 173 }) 174 } 175 }) 176 } 177 } 178 179 func benchUpload(b *testing.B, bucket, key string, reader io.ReadSeeker, sdkConfig SDKConfig, clientConfig ClientConfig) error { 180 uploader := newUploader(clientConfig, sdkConfig, SetUnsignedPayload) 181 _, err := uploader.Upload(&s3manager.UploadInput{ 182 Bucket: &bucket, 183 Key: &key, 184 Body: reader, 185 }) 186 if err != nil { 187 return err 188 } 189 return nil 190 } 191 192 func TestMain(m *testing.M) { 193 benchConfig.SetupFlags("", flag.CommandLine) 194 flag.Parse() 195 os.Exit(m.Run()) 196 }