Skip to content

Commit

Permalink
benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
gavincabbage committed May 9, 2019
1 parent daa3ea2 commit 71aed52
Show file tree
Hide file tree
Showing 11 changed files with 219 additions and 127 deletions.
64 changes: 43 additions & 21 deletions chiv_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
package chiv_test

import (
"fmt"
"math/rand"
"os"
"testing"
"time"

"github.com/aws/aws-sdk-go/service/s3/s3manager"

Expand All @@ -14,39 +17,58 @@ import (
)

func BenchmarkArchiver_Archive(b *testing.B) {
const (
bucket = "benchmark_bucket"
table = "benchmark_table"

createTable = "CREATE TABLE IF NOT EXISTS benchmark_table (s_col TEXT, d_col INTEGER, f_col DECIMAL);"
insertIntoTable = "INSERT INTO benchmark_table VALUES ('%s', %d, %f);"
dropTable = "DROP TABLE benchmark_table;"

charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
textLength = 1000
)

var (
db = newDB(b, "postgres", os.Getenv("POSTGRES_URL"))
s3client = newS3Client(b, os.Getenv("AWS_REGION"), os.Getenv("AWS_ENDPOINT"))
uploader = s3manager.NewUploaderWithClient(s3client)
r = rand.New(rand.NewSource(time.Now().Unix()))

benchmarks = []int{1, 10, 100, 1000, 2000, 3000, 5000, 10000}
)

const (
createTable = `CREATE TABLE IF NOT EXISTS "benchmark_table" (t TEXT,i INTEGER,f DECIMAL);`
for _, count := range benchmarks {
exec(b, db, createTable)
createBucket(b, s3client, bucket)

insertIntoTable = `INSERT INTO "benchmark_table" VALUES (%s,
2345,
);`
for i := 0; i < count; i++ {
statement := fmt.Sprintf(insertIntoTable, text(r, charset, textLength), i, 1.0)
exec(b, db, statement)
}

dropTable = `
DROP TABLE "benchmark_table";`
)
subject := chiv.NewArchiver(db, uploader)

exec(b, db, createTable)
defer exec(b, db, dropTable)
b.Run(fmt.Sprintf("benchmark_%d", count), func(*testing.B) {
for j := 0; j < b.N; j++ {
key := fmt.Sprintf("benchmark_%d_%d", count, j)
if err := subject.Archive(table, bucket, chiv.WithKey(key)); err != nil {
b.Error(err)
}
}
})

for i := 0; i < 100; i++ {
exec(b, db, insertIntoTable)
exec(b, db, dropTable)
deleteBucket(b, s3client, bucket)
}

createBucket(b, s3client, "benchmark_bucket")

subject := chiv.NewArchiver(db, uploader)
}

b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := subject.Archive("benchmark_table", "benchmark_bucket", chiv.WithKey("benchmark_"+string(i))); err != nil {
b.Error(err)
}
func text(r *rand.Rand, charset string, length int) string {
b := make([]byte, length)
for i := range b {
b[i] = charset[r.Intn(len(charset))]
}

return string(b)
}
102 changes: 13 additions & 89 deletions chiv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,9 @@
package chiv_test

import (
"database/sql"
"io/ioutil"
"os"
"strings"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand All @@ -28,14 +21,14 @@ type test struct {
database string
setup string
teardown string
bucket string
options []chiv.Option
calls []call
}

type call struct {
expected string
table string
bucket string
key string
options []chiv.Option
}
Expand All @@ -48,11 +41,11 @@ func TestArchiver_Archive(t *testing.T) {
database: os.Getenv("POSTGRES_URL"),
setup: "./test/data/postgres_setup.sql",
teardown: "./test/data/postgres_teardown.sql",
bucket: "postgres_bucket",
options: []chiv.Option{},
calls: []call{
{
expected: "./test/data/postgres.csv",
bucket: "postgres_bucket",
table: "postgres_table",
key: "postgres_table",
options: []chiv.Option{},
Expand All @@ -65,13 +58,13 @@ func TestArchiver_Archive(t *testing.T) {
database: os.Getenv("POSTGRES_URL"),
setup: "./test/data/postgres_setup.sql",
teardown: "./test/data/postgres_teardown.sql",
bucket: "postgres_bucket",
options: []chiv.Option{
chiv.WithKey("postgres_table.csv"),
},
calls: []call{
{
expected: "./test/data/postgres.csv",
bucket: "postgres_bucket",
table: "postgres_table",
key: "postgres_table.csv",
options: []chiv.Option{},
Expand All @@ -84,13 +77,13 @@ func TestArchiver_Archive(t *testing.T) {
database: os.Getenv("POSTGRES_URL"),
setup: "./test/data/postgres_setup.sql",
teardown: "./test/data/postgres_teardown.sql",
bucket: "postgres_bucket",
options: []chiv.Option{
chiv.WithNull("custom_null"),
},
calls: []call{
{
expected: "./test/data/postgres_with_null.csv",
bucket: "postgres_bucket",
table: "postgres_table",
key: "postgres_table",
options: []chiv.Option{},
Expand All @@ -103,14 +96,14 @@ func TestArchiver_Archive(t *testing.T) {
database: os.Getenv("POSTGRES_URL"),
setup: "./test/data/postgres_setup.sql",
teardown: "./test/data/postgres_teardown.sql",
bucket: "postgres_bucket",
options: []chiv.Option{
chiv.WithFormat(chiv.JSON),
chiv.WithKey("postgres_table.json"),
},
calls: []call{
{
expected: "./test/data/postgres.json",
bucket: "postgres_bucket",
table: "postgres_table",
key: "postgres_table.json",
options: []chiv.Option{},
Expand All @@ -123,14 +116,14 @@ func TestArchiver_Archive(t *testing.T) {
database: os.Getenv("POSTGRES_URL"),
setup: "./test/data/postgres_setup.sql",
teardown: "./test/data/postgres_teardown.sql",
bucket: "postgres_bucket",
options: []chiv.Option{
chiv.WithFormat(chiv.YAML),
chiv.WithKey("postgres_table.yaml"),
},
calls: []call{
{
expected: "./test/data/postgres.yaml",
bucket: "postgres_bucket",
table: "postgres_table",
key: "postgres_table.yaml",
options: []chiv.Option{},
Expand All @@ -143,13 +136,13 @@ func TestArchiver_Archive(t *testing.T) {
database: os.Getenv("POSTGRES_URL"),
setup: "./test/data/postgres_setup.sql",
teardown: "./test/data/postgres_teardown.sql",
bucket: "postgres_bucket",
options: []chiv.Option{
chiv.WithFormat(chiv.YAML),
},
calls: []call{
{
expected: "./test/data/postgres.json",
bucket: "postgres_bucket",
table: "postgres_table",
key: "postgres_table.json",
options: []chiv.Option{
Expand All @@ -159,7 +152,6 @@ func TestArchiver_Archive(t *testing.T) {
},
{
expected: "./test/data/postgres.yaml",
bucket: "postgres_bucket",
table: "postgres_table",
key: "postgres_table.yaml",
options: []chiv.Option{
Expand All @@ -182,87 +174,19 @@ func TestArchiver_Archive(t *testing.T) {
exec(t, db, readFile(t, test.setup))
defer exec(t, db, readFile(t, test.teardown))

createBucket(t, s3client, test.bucket)
defer deleteBucket(t, s3client, test.bucket)

subject := chiv.NewArchiver(db, uploader, test.options...)
assert.NotNil(t, subject)

for _, call := range test.calls {
createBucket(t, s3client, call.bucket)
expected := readFile(t, call.expected)
require.NoError(t, subject.Archive(call.table, test.bucket, call.options...))

require.NoError(t, subject.Archive(call.table, call.bucket, call.options...))

actual := download(t, downloader, call.bucket, call.key)
expected := readFile(t, call.expected)
actual := download(t, downloader, test.bucket, call.key)
require.Equal(t, expected, actual)
}
})
}
}

func newDB(e errorer, driver string, url string) *sql.DB {
db, err := sql.Open(driver, url)
if err != nil {
e.Error(err)
}

return db
}

func newS3Client(e errorer, region string, endpoint string) *s3.S3 {
awsConfig := aws.NewConfig().
WithRegion(region).
WithDisableSSL(true).
WithCredentials(credentials.NewEnvCredentials())

awsSession, err := session.NewSession(awsConfig)
if err != nil {
e.Error(err)
}

client := s3.New(awsSession)
client.Endpoint = endpoint

return client
}

func exec(e errorer, db *sql.DB, statements string) {
s := strings.Split(statements, ";\n\n")
for _, statement := range s {
if _, err := db.Exec(statement); err != nil {
e.Error(err)
}
}
}

func createBucket(e errorer, client *s3.S3, name string) {
if _, err := client.CreateBucket(&s3.CreateBucketInput{
Bucket: aws.String(name),
}); err != nil {
e.Error(err)
}
}

func readFile(e errorer, path string) string {
contents, err := ioutil.ReadFile(path)
if err != nil {
e.Error(err)
}

return string(contents)
}

func download(e errorer, downloader *s3manager.Downloader, bucket string, key string) string {
b := &aws.WriteAtBuffer{}
_, err := downloader.Download(b, &s3.GetObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
})
if err != nil {
e.Error(err)
}

return string(b.Bytes())
}

type errorer interface {
Error(...interface{})
}
2 changes: 1 addition & 1 deletion codeship-services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ s3:
image: localstack/localstack:latest
environment:
- SERVICES=s3
cached: true
cached: true
22 changes: 11 additions & 11 deletions codeship-steps.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
- type: parallel
steps:
- name: lint
service: lint
command: golangci-lint run
- name: test
service: test
command: go test -p 1 -covermode=atomic -timeout=30s ./...
- name: bench
service: test
command: go test -run=Benchmark -bench=. -benchmem
- name: lint
service: lint
command: golangci-lint run

- name: test
service: test
command: go test -p 1 -covermode=atomic -timeout=30s ./...

- name: benchmark
service: test
command: go test -run=Benchmark -bench=. -benchmem
Loading

0 comments on commit 71aed52

Please sign in to comment.