結論
この記事では、以下の結論となっています。
- DynamoDBLocal が LocalStack の DynamoDB よりパフォーマンスが良い
- 自動テストでは、DynamoDBLocal を使うほうが良い
概要
手元のPCで動く開発用 DynamoDB は以下の2つがあります。
私が担当しているプロジェクトでは、LocalStack の DynamoDB を採用していました。自動テストが増えていくたびに、テスト時間が長くなってしまっていたので、試しに DynamoDB Local に置き換えたら、劇的にテスト実行時間が短くなりました。
ということで、どのくらいの差があるのか気になったので、ベンチマークを取ってみました。
ベンチマークのやり方
ベンチマークのやり方は以下のようにしました。
- Go言語のベンチマーク機能を使用する
- DynamoDB に N 回書き込む処理を実行する
- 1処理にどのくらい時間がかかったのかを比較する
ベンチマークの結果
実行結果の出力は以下のようになりました。
BenchmarkDynamoLocal-8 20 90542206 ns/op BenchmarkLocalStack-8 3 695957779 ns/op
この結果に関して言えば、
DynamoDBLocal が LocalStack よりも 約 7.5 倍 早いことになります。
コード
コードも載せておきます。 DynamoDBに書き込む処理を実装したコードになります。
package dynamo_bench import ( "fmt" "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/guregu/dynamo" "github.com/pkg/errors" ) type Table struct { PK string `dynamo:"PK,hash"` SK string `dynamo:"SK,range"` } // Config 接続設定 func Config(endpoint string) *aws.Config { return &aws.Config{ Region: aws.String("ap-northeast-1"), Credentials: credentials.NewStaticCredentials("dummy", "dummy", "dummy"), Endpoint: aws.String(endpoint), } } // ConnectDB DynamoDBに接続する func ConnectDB(endpoint string) (*dynamo.DB, error) { sess, err := session.NewSession(Config(endpoint)) if err != nil { return nil, errors.WithStack(err) } return dynamo.New(sess), nil } // CreateTable DynamoDBにテーブルを作成する func CreateTable(db *dynamo.DB) error { return db.CreateTable("Table", Table{}).Run() } // CreateRecords DynamoDBのテーブルにn回書き込む func CreateRecords(db *dynamo.DB, n int) error { for i := 0; i < n; i++ { err := db.Table("Table").Put(&Table{ PK: fmt.Sprintf("PK%d", i), SK: fmt.Sprintf("SK%d", i), }).Run() if err != nil { return err } } return nil }
ベンチマーク実行コードです。
package dynamo_bench import ( "os" "testing" ) func bench(b *testing.B, endpoint string) { b.Helper() db, err := ConnectDB(endpoint) if err != nil { b.Error(err) } CreateTable(db) err = CreateRecords(db, b.N) if err != nil { b.Error(err) } } func BenchmarkDynamoLocal(b *testing.B) { bench(b, os.Getenv("DYNAMOLOCAL")) } func BenchmarkLocalStack(b *testing.B) { bench(b, os.Getenv("LOCALSTACK")) }
以下のように実行します。
$ go test -bench .
リポジトリ
今回実行したコードは、以下に置いておきました。