メメメモモ

プログラミング、筋トレ、ゲーム、etc

LocalStack の DynamoDB と DynamoDBLocal のベンチマークを取ってみた

結論

この記事では、以下の結論となっています。

  • 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 .

リポジトリ

今回実行したコードは、以下に置いておきました。

github.com