Skip to content

Commit c99ba0c

Browse files
feat(s3-perf-test): parameterize the block size testing
1 parent ad7d764 commit c99ba0c

File tree

1 file changed

+56
-10
lines changed

1 file changed

+56
-10
lines changed

s3-perf-test/main.go

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ func main() {
2828
objectCount := os.Getenv("MAX_OBJECTS")
2929
testDuration := os.Getenv("TEST_DURATION")
3030
useSSL := os.Getenv("USE_SSL")
31+
readSizeKB := os.Getenv("READ_SIZE_KB")
32+
readBufferSizeKB := os.Getenv("READ_BUFFER_SIZE_KB")
3133

3234
if accessKeyID == "" || secretKey == "" {
3335
slog.Error("S3_ACCESS_KEY_ID and S3_ACCESS_KEY_SECRET_KEY are required to run")
@@ -90,9 +92,43 @@ func main() {
9092
}
9193
}
9294

95+
// 16KiB by default
96+
readSize := int64(16 * 1024)
97+
if readSizeKB != "" {
98+
val, err := strconv.Atoi(readSizeKB)
99+
if err != nil {
100+
slog.Error("failed to parse READ_SIZE_KB", "error", err)
101+
102+
os.Exit(1)
103+
}
104+
105+
readSize = int64(val * 1024)
106+
}
107+
108+
// 32KiB by default
109+
readBufferSize := 32 * 1024
110+
if readBufferSizeKB != "" {
111+
val, err := strconv.Atoi(readBufferSizeKB)
112+
if err != nil {
113+
slog.Error("failed to parse READ_BUFFER_SIZE_KB", "error", err)
114+
115+
os.Exit(1)
116+
}
117+
118+
readBufferSize = val * 1024
119+
}
120+
93121
ctx, cancel := context.WithCancel(context.Background())
94122
transport := cleanhttp.DefaultPooledTransport()
95123

124+
// Modify some defaults to be more performant
125+
transport.MaxConnsPerHost = threads
126+
transport.DisableCompression = true
127+
128+
// Our test only reads so just bump both buffers
129+
transport.ReadBufferSize = readBufferSize
130+
transport.WriteBufferSize = readBufferSize
131+
96132
s3Client, err := minio.New(endpoint, &minio.Options{
97133
Creds: credentials.NewStaticV4(accessKeyID, secretKey, ""),
98134
Secure: ssl,
@@ -137,10 +173,13 @@ func main() {
137173
Objects: objects,
138174
ObjectSizes: sizes,
139175
S3Client: s3Client,
176+
BlockSize: readSize,
140177
}
141178

142179
start := time.Now().UTC()
143180

181+
slog.Info("starting test")
182+
144183
for i := range threads {
145184
wg.Add(1)
146185
go func() {
@@ -160,17 +199,22 @@ func main() {
160199

161200
aggregatedBytesRead := 0
162201
aggregatedRequestsSent := 0
163-
var averageTTLB int64
202+
var (
203+
averageTTLB int64
204+
averageTestTime int64
205+
)
164206

165207
for range threads {
166208
result := <-resultChan
167209

168210
aggregatedBytesRead += int(result.TotalBytesRead)
169211
aggregatedRequestsSent += int(result.TotalRequestsSent)
170212
averageTTLB += result.TotalTTLBMS
213+
averageTestTime += result.TotalTestTimeMS
171214
}
172215

173216
averageTTLB = averageTTLB / int64(aggregatedRequestsSent)
217+
averageTestTime = averageTestTime / int64(aggregatedRequestsSent)
174218

175219
timeSpent := time.Since(start)
176220

@@ -181,12 +225,14 @@ func main() {
181225
t.AppendRow(table.Row{"Total Bytes Read", fmt.Sprintf("%d", aggregatedBytesRead)})
182226
t.AppendRow(table.Row{"Total Requests Sent", fmt.Sprintf("%d", aggregatedRequestsSent)})
183227
t.AppendRow(table.Row{"Average TTLB", fmt.Sprintf("%d", averageTTLB)})
228+
t.AppendRow(table.Row{"Average Test Time", fmt.Sprintf("%d", averageTestTime)})
184229

185230
t.Render()
186231
}
187232

188233
type testParams struct {
189234
Bucket string
235+
BlockSize int64
190236
RNG *rand.Rand
191237
Objects []string
192238
ObjectSizes []int64
@@ -196,40 +242,38 @@ type testParams struct {
196242
type testResult struct {
197243
TotalBytesRead int64
198244
TotalRequestsSent int64
245+
TotalTestTimeMS int64
199246
TotalTTLBMS int64
200247
}
201248

202249
func runTest(ctx context.Context, params *testParams, id int) *testResult {
203250
ll := slog.With("ID", id)
204251

205-
ll.Info("starting test")
206-
207252
result := &testResult{}
208253

209254
testCtx := context.Background()
210255

211256
for {
212257
select {
213258
case <-ctx.Done():
214-
ll.Info("context cancelled, stopping test")
215-
216259
return result
217260
default:
261+
testStart := time.Now().UTC()
218262
// Get our random object
219263
randObjIndex := params.RNG.Int() % len(params.Objects)
220264
obj := params.Objects[randObjIndex]
221265
size := params.ObjectSizes[randObjIndex]
222266

223267
// Get a random 16KiB offset to read
224-
maxOffset := size / (16 * 1024)
268+
maxOffset := size / params.BlockSize
225269
randObjOffset := params.RNG.Int() % int(maxOffset)
226270

227-
rangeStart := int64(randObjOffset * (16 * 1024))
228-
rangeEnd := min(int64((rangeStart + (16 * 1024))), size)
271+
rangeStart := int64(randObjOffset) * params.BlockSize
272+
rangeEnd := min((rangeStart + params.BlockSize), size)
229273

230274
result.TotalRequestsSent++
231275

232-
start := time.Now().UTC()
276+
reqStart := time.Now().UTC()
233277

234278
reqOpts := minio.GetObjectOptions{}
235279
reqOpts.SetRange(rangeStart, rangeEnd)
@@ -246,7 +290,9 @@ func runTest(ctx context.Context, params *testParams, id int) *testResult {
246290
resp.Close()
247291

248292
result.TotalBytesRead += amount
249-
result.TotalTTLBMS += time.Since(start).Milliseconds()
293+
result.TotalTTLBMS += time.Since(reqStart).Milliseconds()
294+
295+
result.TotalTestTimeMS += time.Since(testStart).Milliseconds()
250296

251297
if err != nil {
252298
ll.Error("failed to discard response body", "error", err)

0 commit comments

Comments
 (0)