add performance benchmarks (#2021)
* update uplink cmd args * add uplod/download benchmark, add script to run benchmarks * fix lint err * changes per CR comments * export env var for linux * fix lint * add byte count to bench test
This commit is contained in:
parent
8f078d2841
commit
6f23aeef18
183
cmd/uplink/cmd/cp_test.go
Normal file
183
cmd/uplink/cmd/cp_test.go
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
// Copyright (C) 2019 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
package cmd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"storj.io/storj/internal/memory"
|
||||||
|
"storj.io/storj/internal/s3client"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
bucket = "testbucket"
|
||||||
|
)
|
||||||
|
|
||||||
|
var benchmarkCases = []struct {
|
||||||
|
name string
|
||||||
|
objectsize memory.Size
|
||||||
|
}{
|
||||||
|
{"100B", 100 * memory.B},
|
||||||
|
{"1MB", 1 * memory.MiB},
|
||||||
|
{"10MB", 10 * memory.MiB},
|
||||||
|
{"100MB", 100 * memory.MiB},
|
||||||
|
{"1G", 1 * memory.GiB},
|
||||||
|
}
|
||||||
|
|
||||||
|
var testObjects = createObjects()
|
||||||
|
|
||||||
|
// createObjects generates the objects (i.e. slice of bytes) that
|
||||||
|
// will be used as the objects to upload/download tests
|
||||||
|
func createObjects() map[string][]byte {
|
||||||
|
objects := make(map[string][]byte)
|
||||||
|
for _, bm := range benchmarkCases {
|
||||||
|
data := make([]byte, bm.objectsize)
|
||||||
|
_, err := rand.Read(data)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to read random bytes: %+v\n", err)
|
||||||
|
}
|
||||||
|
objects[bm.name] = data
|
||||||
|
}
|
||||||
|
return objects
|
||||||
|
}
|
||||||
|
|
||||||
|
// uplinkSetup setups an uplink to use for testing uploads/downloads
|
||||||
|
func uplinkSetup() s3client.Client {
|
||||||
|
conf, err := setupConfig()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to setup s3client config: %+v\n", err)
|
||||||
|
}
|
||||||
|
client, err := s3client.NewUplink(conf)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to create s3client NewUplink: %+v\n", err)
|
||||||
|
}
|
||||||
|
err = client.MakeBucket(bucket, "")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to create bucket with s3client %q: %+v\n", bucket, err)
|
||||||
|
}
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupConfig() (s3client.Config, error) {
|
||||||
|
const (
|
||||||
|
uplinkEncryptionKey = "supersecretkey"
|
||||||
|
defaultSatelliteAddr = "127.0.0.1:10000"
|
||||||
|
)
|
||||||
|
var conf s3client.Config
|
||||||
|
conf.EncryptionKey = uplinkEncryptionKey
|
||||||
|
conf.Satellite = getEnvOrDefault("SATELLITE_0_ADDR", defaultSatelliteAddr)
|
||||||
|
conf.APIKey = getEnvOrDefault(os.Getenv("GATEWAY_0_API_KEY"), os.Getenv("apiKey"))
|
||||||
|
if conf.APIKey == "" {
|
||||||
|
return conf, errors.New("no api key provided. Expecting an env var $GATEWAY_0_API_KEY or $apiKey")
|
||||||
|
}
|
||||||
|
return conf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEnvOrDefault(key, fallback string) string {
|
||||||
|
if value, exists := os.LookupEnv(key); exists {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUpload(b *testing.B) {
|
||||||
|
var client = uplinkSetup()
|
||||||
|
|
||||||
|
// uploadedObjects is used to store the names of all objects that are uploaded
|
||||||
|
// so that we can make sure to delete them all during cleanup
|
||||||
|
var uploadedObjects = map[string][]string{}
|
||||||
|
|
||||||
|
for _, bm := range benchmarkCases {
|
||||||
|
b.Run(bm.name, func(b *testing.B) {
|
||||||
|
b.SetBytes(bm.objectsize.Int64())
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
// make some random bytes so the objectPath is unique
|
||||||
|
randomBytes := make([]byte, 16)
|
||||||
|
rand.Read(randomBytes)
|
||||||
|
uniquePathPart := hex.EncodeToString(randomBytes)
|
||||||
|
objectPath := "folder/data" + uniquePathPart + "_" + bm.name
|
||||||
|
err := client.Upload(bucket, objectPath, testObjects[bm.name])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to upload object %q: %+v\n", objectPath, err)
|
||||||
|
}
|
||||||
|
if uploadedObjects[bm.name] == nil {
|
||||||
|
uploadedObjects[bm.name] = []string{}
|
||||||
|
}
|
||||||
|
uploadedObjects[bm.name] = append(uploadedObjects[bm.name], objectPath)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown(client, uploadedObjects)
|
||||||
|
}
|
||||||
|
|
||||||
|
func teardown(client s3client.Client, uploadedObjects map[string][]string) {
|
||||||
|
for _, bm := range benchmarkCases {
|
||||||
|
for _, objectPath := range uploadedObjects[bm.name] {
|
||||||
|
err := client.Delete(bucket, objectPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failed to delete object %q: %+v\n", objectPath, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := client.RemoveBucket(bucket)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to remove bucket %q: %+v\n", bucket, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDownload(b *testing.B) {
|
||||||
|
var client = uplinkSetup()
|
||||||
|
|
||||||
|
// upload some test objects so that there is something to download
|
||||||
|
uploadTestObjects(client)
|
||||||
|
|
||||||
|
for _, bm := range benchmarkCases {
|
||||||
|
b.Run(bm.name, func(b *testing.B) {
|
||||||
|
buf := make([]byte, bm.objectsize)
|
||||||
|
b.SetBytes(bm.objectsize.Int64())
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
objectName := "folder/data_" + bm.name
|
||||||
|
_, err := client.Download(bucket, objectName, buf)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to download object %q: %+v\n", objectName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
teardownTestObjects(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func uploadTestObjects(client s3client.Client) {
|
||||||
|
for name, data := range testObjects {
|
||||||
|
objectName := "folder/data_" + name
|
||||||
|
err := client.Upload(bucket, objectName, data)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to upload object %q: %+v\n", objectName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func teardownTestObjects(client s3client.Client) {
|
||||||
|
for name := range testObjects {
|
||||||
|
objectName := "folder/data_" + name
|
||||||
|
err := client.Delete(bucket, objectName)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to delete object %q: %+v\n", objectName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err := client.RemoveBucket(bucket)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to remove bucket %q: %+v\n", bucket, err)
|
||||||
|
}
|
||||||
|
}
|
@ -5,11 +5,15 @@ package s3client
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/zeebo/errs"
|
"github.com/zeebo/errs"
|
||||||
|
|
||||||
|
"storj.io/storj/internal/fpath"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UplinkError is class for minio errors
|
// UplinkError is class for minio errors
|
||||||
@ -24,16 +28,38 @@ type Uplink struct {
|
|||||||
func NewUplink(conf Config) (Client, error) {
|
func NewUplink(conf Config) (Client, error) {
|
||||||
client := &Uplink{conf}
|
client := &Uplink{conf}
|
||||||
|
|
||||||
cmd := client.cmd("setup",
|
defaultConfDir := fpath.ApplicationDir("storj", "uplink")
|
||||||
"--overwrite",
|
setupDir, err := filepath.Abs(defaultConfDir)
|
||||||
"--api-key", client.conf.APIKey,
|
|
||||||
"--enc-key", client.conf.EncryptionKey,
|
|
||||||
"--satellite-addr", client.conf.Satellite)
|
|
||||||
|
|
||||||
_, err := cmd.Output()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, UplinkError.Wrap(fullExitError(err))
|
return nil, UplinkError.Wrap(fullExitError(err))
|
||||||
}
|
}
|
||||||
|
validForSetup, _ := fpath.IsValidSetupDir(setupDir)
|
||||||
|
|
||||||
|
// uplink configuration doesn't exists
|
||||||
|
if validForSetup {
|
||||||
|
fmt.Printf(`No existing uplink configuration located at (%v)...
|
||||||
|
Creating uplink configuration with the following settings:
|
||||||
|
"--non-interactive: true",
|
||||||
|
"--api-key: %s",
|
||||||
|
"--enc.key: %s",
|
||||||
|
"--satellite-addr: %s
|
||||||
|
`,
|
||||||
|
setupDir, client.conf.APIKey, client.conf.EncryptionKey, client.conf.Satellite,
|
||||||
|
)
|
||||||
|
cmd := client.cmd("setup",
|
||||||
|
"--non-interactive", "true",
|
||||||
|
"--api-key", client.conf.APIKey,
|
||||||
|
"--enc.key", client.conf.EncryptionKey,
|
||||||
|
"--satellite-addr", client.conf.Satellite)
|
||||||
|
|
||||||
|
_, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return nil, UplinkError.Wrap(fullExitError(err))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if uplink config file already exists, use the current config
|
||||||
|
fmt.Printf("Using existing uplink configuration from (%v). To pass in new settings, delete existing configs first\n", setupDir)
|
||||||
|
}
|
||||||
|
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
26
scripts/test-sim-benchmark.sh
Executable file
26
scripts/test-sim-benchmark.sh
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -ueo pipefail
|
||||||
|
|
||||||
|
# Purpose: This script executes uplink upload and download benchmark tests against storj-sim.
|
||||||
|
# Setup: Remove any existing uplink configs.
|
||||||
|
# Usage: from root of storj repo, run
|
||||||
|
# $ storj-sim network test bash ./scripts/test-sim-benchmark.sh
|
||||||
|
# To run and filter out storj-sim logs, run:
|
||||||
|
# $ storj-sim -x network test bash ./scripts/test-sim-benchmark.sh | grep -i "test.out"
|
||||||
|
|
||||||
|
SATELLITE_0_ADDR=${SATELLITE_0_ADDR:-127.0.0.1}
|
||||||
|
|
||||||
|
apiKey=$(storj-sim network env GATEWAY_0_API_KEY)
|
||||||
|
export apiKey=$(storj-sim network env GATEWAY_0_API_KEY)
|
||||||
|
echo "apiKey:"
|
||||||
|
echo "$apiKey"
|
||||||
|
|
||||||
|
# run benchmark tests normally
|
||||||
|
echo
|
||||||
|
echo "Executing benchmark tests locally"
|
||||||
|
go test -bench . -benchmem ./cmd/uplink/cmd/
|
||||||
|
|
||||||
|
# run s3-benchmark with uplink
|
||||||
|
echo
|
||||||
|
echo "Executing s3-benchmark tests with uplink client..."
|
||||||
|
s3-benchmark --client=uplink --satellite="$SATELLITE_0_ADDR" --apikey="$apiKey"
|
Loading…
Reference in New Issue
Block a user