github.com/thiagoyeds/go-cloud@v0.26.0/docstore/awsdynamodb/benchmark_test.go (about) 1 // Copyright 2019 The Go Cloud Development Kit Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package awsdynamodb 16 17 import ( 18 "fmt" 19 "net/http" 20 "strconv" 21 "testing" 22 23 "github.com/aws/aws-sdk-go/aws" 24 awscreds "github.com/aws/aws-sdk-go/aws/credentials" 25 "github.com/aws/aws-sdk-go/aws/session" 26 "github.com/aws/aws-sdk-go/service/dynamodb" 27 dyn "github.com/aws/aws-sdk-go/service/dynamodb" 28 "github.com/aws/aws-sdk-go/service/dynamodb/expression" 29 ) 30 31 var benchmarkTableName = collectionName3 32 33 func BenchmarkPutVSTransact(b *testing.B) { 34 // This benchmark compares two ways to replace N items and retrieve their previous values. 35 // The first way makes N calls to PutItem with ReturnValues set to ALL_OLD. 36 // The second way calls BatchGetItem followed by TransactWriteItem. 37 // 38 // The results show that separate PutItems are faster for up to two items. 39 sess, err := awsSession(region, http.DefaultClient) 40 if err != nil { 41 b.Fatal(err) 42 } 43 db := dynamodb.New(sess) 44 45 for nItems := 1; nItems <= 5; nItems++ { 46 b.Run(fmt.Sprintf("%d-Items", nItems), func(b *testing.B) { 47 var items []map[string]*dynamodb.AttributeValue 48 for i := 0; i < nItems; i++ { 49 items = append(items, map[string]*dynamodb.AttributeValue{ 50 "name": new(dyn.AttributeValue).SetS(fmt.Sprintf("pt-vs-transact-%d", i)), 51 "x": new(dyn.AttributeValue).SetN(strconv.Itoa(i)), 52 "rev": new(dyn.AttributeValue).SetN("1"), 53 }) 54 } 55 for _, item := range items { 56 _, err := db.PutItem(&dynamodb.PutItemInput{ 57 TableName: &benchmarkTableName, 58 Item: item, 59 }) 60 if err != nil { 61 b.Fatal(err) 62 } 63 } 64 b.Run("PutItem", func(b *testing.B) { 65 for n := 0; n < b.N; n++ { 66 putItems(b, db, items) 67 } 68 }) 69 b.Run("TransactWrite", func(b *testing.B) { 70 for n := 0; n < b.N; n++ { 71 batchGetTransactWrite(b, db, items) 72 } 73 }) 74 }) 75 76 } 77 } 78 79 func putItems(b *testing.B, db *dynamodb.DynamoDB, items []map[string]*dynamodb.AttributeValue) { 80 for i, item := range items { 81 item["x"].SetN(strconv.Itoa(i + 1)) 82 in := &dynamodb.PutItemInput{ 83 TableName: &benchmarkTableName, 84 Item: item, 85 ReturnValues: aws.String("ALL_OLD"), 86 } 87 ce, err := expression.NewBuilder(). 88 WithCondition(expression.Name("rev").Equal(expression.Value(1))). 89 Build() 90 if err != nil { 91 b.Fatal(err) 92 } 93 in.ExpressionAttributeNames = ce.Names() 94 in.ExpressionAttributeValues = ce.Values() 95 in.ConditionExpression = ce.Condition() 96 out, err := db.PutItem(in) 97 if err != nil { 98 b.Fatal(err) 99 } 100 if got, want := len(out.Attributes), 3; got != want { 101 b.Fatalf("got %d attributes, want %d", got, want) 102 } 103 } 104 } 105 106 func batchGetTransactWrite(b *testing.B, db *dynamodb.DynamoDB, items []map[string]*dynamodb.AttributeValue) { 107 keys := make([]map[string]*dynamodb.AttributeValue, len(items)) 108 tws := make([]*dyn.TransactWriteItem, len(items)) 109 for i, item := range items { 110 keys[i] = map[string]*dynamodb.AttributeValue{"name": items[i]["name"]} 111 item["x"].SetN(strconv.Itoa(i + 2)) 112 put := &dynamodb.Put{TableName: &benchmarkTableName, Item: items[i]} 113 ce, err := expression.NewBuilder(). 114 WithCondition(expression.Name("rev").Equal(expression.Value(1))). 115 Build() 116 if err != nil { 117 b.Fatal(err) 118 } 119 put.ExpressionAttributeNames = ce.Names() 120 put.ExpressionAttributeValues = ce.Values() 121 put.ConditionExpression = ce.Condition() 122 tws[i] = &dynamodb.TransactWriteItem{Put: put} 123 } 124 _, err := db.BatchGetItem(&dynamodb.BatchGetItemInput{ 125 RequestItems: map[string]*dynamodb.KeysAndAttributes{ 126 benchmarkTableName: {Keys: keys}, 127 }, 128 }) 129 if err != nil { 130 b.Fatal(err) 131 } 132 _, err = db.TransactWriteItems(&dynamodb.TransactWriteItemsInput{TransactItems: tws}) 133 if err != nil { 134 b.Fatal(err) 135 } 136 } 137 138 func awsSession(region string, client *http.Client) (*session.Session, error) { 139 // Provide fake creds if running in replay mode. 140 var creds *awscreds.Credentials 141 return session.NewSession(&aws.Config{ 142 HTTPClient: client, 143 Region: aws.String(region), 144 Credentials: creds, 145 MaxRetries: aws.Int(0), 146 }) 147 }