github.com/aavshr/aws-sdk-go@v1.41.3/awstesting/integration/performance/s3DownloadManager/main_test.go (about) 1 //go:build go1.13 && integration && perftest 2 // +build go1.13,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/awstesting" 16 "github.com/aavshr/aws-sdk-go/awstesting/integration" 17 "github.com/aavshr/aws-sdk-go/internal/sdkio" 18 "github.com/aavshr/aws-sdk-go/service/s3" 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 uploadPartSize int64 33 } 34 35 func (b *BenchmarkConfig) SetupFlags(prefix string, flagSet *flag.FlagSet) { 36 flagSet.StringVar(&b.bucket, "bucket", "", "Bucket to use for benchmark") 37 flagSet.StringVar(&b.tempdir, "temp", os.TempDir(), "location to create temporary files") 38 39 flagSet.StringVar(&b.sizes, "size", 40 fmt.Sprintf("%d,%d", 41 5*sdkio.MebiByte, 42 1*sdkio.GibiByte), "file sizes to benchmark separated by comma") 43 44 flagSet.StringVar(&b.parts, "part", 45 fmt.Sprintf("%d,%d,%d", 46 s3manager.DefaultDownloadPartSize, 47 25*sdkio.MebiByte, 48 100*sdkio.MebiByte), "part sizes to benchmark separated by comma") 49 50 flagSet.StringVar(&b.concurrency, "concurrency", 51 fmt.Sprintf("%d,%d,%d", 52 s3manager.DefaultDownloadConcurrency, 53 2*s3manager.DefaultDownloadConcurrency, 54 100), 55 "part sizes to benchmark separated comma") 56 57 flagSet.StringVar(&b.bufferSize, "buffer", fmt.Sprintf("%d,%d", 0, 1*sdkio.MebiByte), "part sizes to benchmark separated comma") 58 flagSet.Int64Var(&b.uploadPartSize, "upload-part-size", 0, "upload part size, defaults to download part size if not specified") 59 b.clientConfig.SetupFlags(prefix, flagSet) 60 } 61 62 func (b *BenchmarkConfig) BufferSizes() []int { 63 ints, err := b.stringToInt(b.bufferSize) 64 if err != nil { 65 panic(fmt.Sprintf("failed to parse file sizes: %v", err)) 66 } 67 68 return ints 69 } 70 71 func (b *BenchmarkConfig) FileSizes() []int64 { 72 ints, err := b.stringToInt64(b.sizes) 73 if err != nil { 74 panic(fmt.Sprintf("failed to parse file sizes: %v", err)) 75 } 76 77 return ints 78 } 79 80 func (b *BenchmarkConfig) PartSizes() []int64 { 81 ints, err := b.stringToInt64(b.parts) 82 if err != nil { 83 panic(fmt.Sprintf("failed to parse part sizes: %v", err)) 84 } 85 86 return ints 87 } 88 89 func (b *BenchmarkConfig) Concurrences() []int { 90 ints, err := b.stringToInt(b.concurrency) 91 if err != nil { 92 panic(fmt.Sprintf("failed to parse part sizes: %v", err)) 93 } 94 95 return ints 96 } 97 98 func (b *BenchmarkConfig) stringToInt(s string) ([]int, error) { 99 int64s, err := b.stringToInt64(s) 100 if err != nil { 101 return nil, err 102 } 103 104 var ints []int 105 for i := range int64s { 106 ints = append(ints, int(int64s[i])) 107 } 108 109 return ints, nil 110 } 111 112 func (b *BenchmarkConfig) stringToInt64(s string) ([]int64, error) { 113 var sizes []int64 114 115 split := strings.Split(s, ",") 116 117 for _, size := range split { 118 size = strings.Trim(size, " ") 119 i, err := strconv.ParseInt(size, 10, 64) 120 if err != nil { 121 return nil, fmt.Errorf("invalid integer %s: %v", size, err) 122 } 123 124 sizes = append(sizes, i) 125 } 126 127 return sizes, nil 128 } 129 130 func BenchmarkDownload(b *testing.B) { 131 baseSdkConfig := SDKConfig{} 132 133 for _, fileSize := range benchConfig.FileSizes() { 134 b.Run(fmt.Sprintf("%s File", integration.SizeToName(int(fileSize))), func(b *testing.B) { 135 for _, partSize := range benchConfig.PartSizes() { 136 if partSize > fileSize { 137 continue 138 } 139 uploadPartSize := getUploadPartSize(fileSize, benchConfig.uploadPartSize, partSize) 140 b.Run(fmt.Sprintf("%s PartSize", integration.SizeToName(int(partSize))), func(b *testing.B) { 141 b.Logf("setting up s3 file size") 142 key, err := setupDownloadTest(benchConfig.bucket, fileSize, uploadPartSize) 143 if err != nil { 144 b.Fatalf("failed to setup download test: %v", err) 145 } 146 for _, concurrency := range benchConfig.Concurrences() { 147 b.Run(fmt.Sprintf("%d Concurrency", concurrency), func(b *testing.B) { 148 for _, bufferSize := range benchConfig.BufferSizes() { 149 var name string 150 if bufferSize == 0 { 151 name = "unbuffered" 152 } else { 153 name = fmt.Sprintf("%s buffer", integration.SizeToName(bufferSize)) 154 } 155 b.Run(name, func(b *testing.B) { 156 sdkConfig := baseSdkConfig 157 sdkConfig.Concurrency = concurrency 158 sdkConfig.PartSize = partSize 159 if bufferSize > 0 { 160 sdkConfig.BufferProvider = s3manager.NewPooledBufferedWriterReadFromProvider(bufferSize) 161 } 162 163 b.ResetTimer() 164 for i := 0; i < b.N; i++ { 165 benchDownload(b, benchConfig.bucket, key, &awstesting.DiscardAt{}, sdkConfig, benchConfig.clientConfig) 166 } 167 }) 168 } 169 }) 170 } 171 b.Log("removing test file") 172 err = teardownDownloadTest(benchConfig.bucket, key) 173 if err != nil { 174 b.Fatalf("failed to cleanup test file: %v", err) 175 } 176 }) 177 } 178 }) 179 } 180 } 181 182 func benchDownload(b *testing.B, bucket, key string, body io.WriterAt, sdkConfig SDKConfig, clientConfig ClientConfig) { 183 downloader := newDownloader(clientConfig, sdkConfig) 184 _, err := downloader.Download(body, &s3.GetObjectInput{ 185 Bucket: &bucket, 186 Key: &key, 187 }) 188 if err != nil { 189 b.Fatalf("failed to download object, %v", err) 190 } 191 } 192 193 func TestMain(m *testing.M) { 194 benchConfig.SetupFlags("", flag.CommandLine) 195 flag.Parse() 196 os.Exit(m.Run()) 197 }