Skip to content

Commit

Permalink
Add performance benchmarks for requests and protocol serializers.
Browse files Browse the repository at this point in the history
  • Loading branch information
jasdel committed Aug 19, 2015
1 parent 846cb8a commit 77b2bb7
Show file tree
Hide file tree
Showing 11 changed files with 901 additions and 7 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,6 @@ deps:

api_info:
@go run internal/model/cli/api-info/api-info.go

perf:
@go test -bench . -benchmem -tags 'perf' ./internal/test/perf/...
12 changes: 5 additions & 7 deletions aws/credentials/shared_credentials_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,10 @@ func BenchmarkSharedCredentialsProvider(b *testing.B) {
}

b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, err := p.Retrieve()
if err != nil {
b.Fatal(err)
}
for i := 0; i < b.N; i++ {
_, err := p.Retrieve()
if err != nil {
b.Fatal(err)
}
})
}
}
58 changes: 58 additions & 0 deletions internal/test/perf/dynamodb/dynamodb_live_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// +build perf_live

package dynamodb

import (
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
)

const testPutItemCount = 5000
const testTableName = `perfTable`

func BenchmarkLivePutItem(b *testing.B) {
benchPutItemParallel(1, testPutItemCount, b)
}

func BenchmarkLivePutItemParallel5(b *testing.B) {
benchPutItemParallel(5, testPutItemCount, b)
}

func BenchmarkLivePutItemParallel10(b *testing.B) {
benchPutItemParallel(10, testPutItemCount, b)
}

func BenchmarkLivePutItemParallel20(b *testing.B) {
benchPutItemParallel(20, testPutItemCount, b)
}

func benchPutItemParallel(p, c int, b *testing.B) {
svc := dynamodb.New(&aws.Config{
DisableSSL: aws.Bool(true),
})

av, err := dynamodbattribute.ConvertToMap(dbItem{Key: "MyKey", Data: "MyData"})
if err != nil {
b.Fatal("expect no ConvertToMap errors", err)
}
params := &dynamodb.PutItemInput{
Item: av,
TableName: aws.String(testTableName),
}
b.N = c

b.ResetTimer()
b.SetParallelism(p)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, err = svc.PutItem(params)
if err != nil {
b.Error("expect no request errors", err)
}
}
})
}

61 changes: 61 additions & 0 deletions internal/test/perf/dynamodb/dynamodb_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// +build perf

package dynamodb

import (
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/service"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
"io"
"net/http"
)

type noopReadCloser struct{}

func (r *noopReadCloser) Read(b []byte) (int, error) {
return 0, io.EOF
}
func (r *noopReadCloser) Close() error {
return nil
}

var noopBody = &noopReadCloser{}

func BenchmarkPutItem(b *testing.B) {
cfg := aws.Config{
DisableSSL: aws.Bool(true),
Credentials: credentials.NewStaticCredentials("AKID", "SECRET", ""),
}
server := successRespServer([]byte(`{}`))
cfg.Endpoint = aws.String(server.URL)

svc := dynamodb.New(&cfg)
svc.Handlers.Send.Clear()
svc.Handlers.Send.PushBack(func(r *service.Request) {
r.HTTPResponse = &http.Response{
StatusCode: http.StatusOK,
Status: http.StatusText(http.StatusOK),
Body: noopBody,
}
})

b.ResetTimer()
for i := 0; i < b.N; i++ {
av, err := dynamodbattribute.ConvertToMap(dbItem{Key: "MyKey", Data: "MyData"})
if err != nil {
b.Fatal("benchPutItem, expect no ConvertToMap errors", err)
}
params := &dynamodb.PutItemInput{
Item: av,
TableName: aws.String("tablename"),
}
_, err = svc.PutItem(params)
if err != nil {
b.Error("benchPutItem, expect no request errors", err)
}
}
}
17 changes: 17 additions & 0 deletions internal/test/perf/dynamodb/stub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dynamodb

import (
"net/http/httptest"
"net/http"
)

type dbItem struct {
Key string
Data string
}

func successRespServer(resp []byte) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write(resp)
}))
}
84 changes: 84 additions & 0 deletions internal/test/perf/protocol/ec2query_build_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// +build perf

package protocol

import (
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/service"
"github.com/aws/aws-sdk-go/internal/protocol/ec2query"
"github.com/aws/aws-sdk-go/service/ec2"
)

func BenchmarkEC2QueryBuild_Complex_ec2AuthorizeSecurityGroupEgress(b *testing.B) {
params := &ec2.AuthorizeSecurityGroupEgressInput{
GroupId: aws.String("String"), // Required
CidrIp: aws.String("String"),
DryRun: aws.Bool(true),
FromPort: aws.Int64(1),
IpPermissions: []*ec2.IpPermission{
{ // Required
FromPort: aws.Int64(1),
IpProtocol: aws.String("String"),
IpRanges: []*ec2.IpRange{
{ // Required
CidrIp: aws.String("String"),
},
// More values...
},
PrefixListIds: []*ec2.PrefixListId{
{ // Required
PrefixListId: aws.String("String"),
},
// More values...
},
ToPort: aws.Int64(1),
UserIdGroupPairs: []*ec2.UserIdGroupPair{
{ // Required
GroupId: aws.String("String"),
GroupName: aws.String("String"),
UserId: aws.String("String"),
},
// More values...
},
},
// More values...
},
IpProtocol: aws.String("String"),
SourceSecurityGroupName: aws.String("String"),
SourceSecurityGroupOwnerId: aws.String("String"),
ToPort: aws.Int64(1),
}

benchEC2QueryBuild(b, "AuthorizeSecurityGroupEgress", params)
}

func BenchmarkEC2QueryBuild_Simple_ec2AttachNetworkInterface(b *testing.B) {
params := &ec2.AttachNetworkInterfaceInput{
DeviceIndex: aws.Int64(1), // Required
InstanceId: aws.String("String"), // Required
NetworkInterfaceId: aws.String("String"), // Required
DryRun: aws.Bool(true),
}

benchEC2QueryBuild(b, "AttachNetworkInterface", params)
}

func benchEC2QueryBuild(b *testing.B, opName string, params interface{}) {
svc := service.NewService(nil)
svc.ServiceName = "ec2"
svc.APIVersion = "2015-04-15"

for i := 0; i < b.N; i++ {
r := service.NewRequest(svc, &service.Operation{
Name: opName,
HTTPMethod: "POST",
HTTPPath: "/",
}, params, nil)
ec2query.Build(r)
if r.Error != nil {
b.Fatal("Unexpected error", r.Error)
}
}
}
70 changes: 70 additions & 0 deletions internal/test/perf/protocol/jsonrpc_build_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// +build perf

package protocol

import (
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/service"
"github.com/aws/aws-sdk-go/internal/protocol/jsonrpc"
"github.com/aws/aws-sdk-go/internal/protocol/json/jsonutil"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
"encoding/json"
"bytes"
)

func BenchmarkJSONRPCBuild_Simple_dynamodbPutItem(b *testing.B) {
svc := service.NewService(nil)

params := getDynamodbPutItemParams(b)

for i := 0; i < b.N; i++ {
r := service.NewRequest(svc, &service.Operation{Name: "Operation"}, params, nil)
jsonrpc.Build(r)
if r.Error != nil {
b.Fatal("Unexpected error", r.Error)
}
}
}

func BenchmarkJSONUtilBuild_Simple_dynamodbPutItem(b *testing.B) {
svc := service.NewService(nil)

params := getDynamodbPutItemParams(b)

for i := 0; i < b.N; i++ {
r := service.NewRequest(svc, &service.Operation{Name: "Operation"}, params, nil)
_, err := jsonutil.BuildJSON(r.Params)
if err != nil {
b.Fatal("Unexpected error", err)
}
}
}

func BenchmarkEncodingJSONMarshal_Simple_dynamodbPutItem(b *testing.B) {
params := getDynamodbPutItemParams(b)

for i := 0; i < b.N; i++ {
buf := &bytes.Buffer{}
encoder := json.NewEncoder(buf)
if err := encoder.Encode(params); err != nil {
b.Fatal("Unexpected error", err)
}
}
}

func getDynamodbPutItemParams(b *testing.B) *dynamodb.PutItemInput {
av, err := dynamodbattribute.ConvertToMap(struct {
Key string
Data string
}{Key: "MyKey", Data: "MyData"})
if err != nil {
b.Fatal("benchPutItem, expect no ConvertToMap errors", err)
}
return &dynamodb.PutItemInput{
Item: av,
TableName: aws.String("tablename"),
}
}
Loading

0 comments on commit 77b2bb7

Please sign in to comment.