From 1d003871814a7647da15499a9fcc7da58afc01c9 Mon Sep 17 00:00:00 2001 From: Preston Vasquez Date: Thu, 12 Sep 2024 12:37:42 -0600 Subject: [PATCH 01/10] GODRIVER-2907 Add bulk decryption benchmarks --- testdata/mongocrypt/command.json | 2 +- testdata/mongocrypt/local-key-document.json | 24 +++ x/mongo/driver/mongocrypt/binary.go | 2 +- x/mongo/driver/mongocrypt/binary_test.go | 191 ++++++++++++++++++++ x/mongo/driver/mongocrypt/mem.prof | Bin 0 -> 2138 bytes 5 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 testdata/mongocrypt/local-key-document.json create mode 100644 x/mongo/driver/mongocrypt/binary_test.go create mode 100644 x/mongo/driver/mongocrypt/mem.prof diff --git a/testdata/mongocrypt/command.json b/testdata/mongocrypt/command.json index d04bf7799a..0fa3fee556 100644 --- a/testdata/mongocrypt/command.json +++ b/testdata/mongocrypt/command.json @@ -3,4 +3,4 @@ "filter": { "ssn": "457-55-5462" } -} \ No newline at end of file +} diff --git a/testdata/mongocrypt/local-key-document.json b/testdata/mongocrypt/local-key-document.json new file mode 100644 index 0000000000..b84b05c25f --- /dev/null +++ b/testdata/mongocrypt/local-key-document.json @@ -0,0 +1,24 @@ +{ + "_id": { + "$binary": { + "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", + "subType": "04" + } + }, + "keyMaterial": { + "$binary": { + "base64": "ACR7Hm33dDOAAD7l2ubZhSpSUWK8BkALUY+qW3UgBAEcTV8sBwZnaAWnzDsmrX55dgmYHWfynDlJogC/e33u6pbhyXvFTs5ow9OLCuCWBJ39T/Ivm3kMaZJybkejY0V+uc4UEdHvVVz/SbitVnzs2WXdMGmo1/HmDRrxGYZjewFslquv8wtUHF5pyB+QDlQBd/al9M444/8bJZFbMSmtIg==", + "subType": "00" + } + }, + "creationDate": { + "$date": "2023-08-21T14:28:20.875Z" + }, + "updateDate": { + "$date": "2023-08-21T14:28:20.875Z" + }, + "status": 0, + "masterKey": { + "provider": "local" + } +} diff --git a/x/mongo/driver/mongocrypt/binary.go b/x/mongo/driver/mongocrypt/binary.go index 4e4b51d74b..7abc976457 100644 --- a/x/mongo/driver/mongocrypt/binary.go +++ b/x/mongo/driver/mongocrypt/binary.go @@ -11,6 +11,7 @@ package mongocrypt /* #include +#include // Include for memcpy #include */ import "C" @@ -31,7 +32,6 @@ func newBinary() *binary { } } -// newBinaryFromBytes creates a binary instance from a byte buffer. func newBinaryFromBytes(data []byte) *binary { if len(data) == 0 { return newBinary() diff --git a/x/mongo/driver/mongocrypt/binary_test.go b/x/mongo/driver/mongocrypt/binary_test.go new file mode 100644 index 0000000000..a424e49d1b --- /dev/null +++ b/x/mongo/driver/mongocrypt/binary_test.go @@ -0,0 +1,191 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +//go:build cse +// +build cse + +package mongocrypt + +import ( + "fmt" + "io/ioutil" + "path" + "runtime" + "testing" + "time" + + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/internal/assert" + "go.mongodb.org/mongo-driver/v2/internal/require" + "go.mongodb.org/mongo-driver/v2/x/bsonx/bsoncore" + "go.mongodb.org/mongo-driver/v2/x/mongo/driver/mongocrypt/options" +) + +func resourceToDocumentB(b *testing.B, filename string) bsoncore.Document { + b.Helper() + + content, err := ioutil.ReadFile(path.Join(resourcesDir, filename)) + require.NoError(b, err) + + var doc bsoncore.Document + + err = bson.UnmarshalExtJSON(content, false, &doc) + require.NoError(b, err) + + return doc +} + +func addMongoKeysForBenchmark(b *testing.B, encryptCtx *Context) { + b.Helper() + + if encryptCtx.State() != NeedMongoKeys { + return + } + + _, err := encryptCtx.NextOperation() + require.NoError(b, err) + + // feed result and finish op + err = encryptCtx.AddOperationResult(resourceToDocumentB(b, "local-key-document.json")) + require.NoError(b, err) + + err = encryptCtx.CompleteOperation() + require.NoError(b, err) +} + +// Encrypt 1500 string values of the form "value ". +func encryptBenchmarkDoc(b *testing.B, crypt *MongoCrypt, iter int) bsoncore.Document { + b.Helper() + + const algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + const numOfKeys = 1500 + + // create explicit encryption context and check initial state + keyID := bson.Binary{ + Subtype: 0x04, // 0x04 is UUID subtype + Data: []byte("aaaaaaaaaaaaaaaa"), + } + + encryptOpts := options.ExplicitEncryption().SetAlgorithm(algorithm).SetKeyID(keyID) + doc := bsoncore.NewDocumentBuilder().AppendString("v", fmt.Sprintf("value %v", iter)).Build() + + encryptCtx, err := crypt.CreateExplicitEncryptionContext(doc, encryptOpts) + require.NoError(b, err) + + defer encryptCtx.Close() + + addMongoKeysForBenchmark(b, encryptCtx) + + // perform final encryption + encryptedDoc, err := encryptCtx.Finish() + require.NoError(b, err) + + return encryptedDoc +} + +func decryptBenchmarkDoc(b *testing.B, crypt *MongoCrypt, encryptedDoc bsoncore.Document) bsoncore.Document { + b.Helper() + + // create explicit decryption context and check initial state + decryptCtx, err := crypt.CreateDecryptionContext(encryptedDoc) + require.NoError(b, err) + + defer decryptCtx.Close() + + // perform final decryption + decryptedDoc, err := decryptCtx.Finish() + require.NoError(b, err) + + return decryptedDoc +} + +// create a document of the form: +// { "key1": , "key2": , ... } +func makeFullEncryptBenchmarkDocs(b *testing.B, crypt *MongoCrypt, count int) bsoncore.Document { + bldr := bsoncore.NewDocumentBuilder() + + for i := 0; i < count; i++ { + encDoc := encryptBenchmarkDoc(b, crypt, i) + bldr.AppendValue(fmt.Sprintf("key%v", i), encDoc.Lookup("v")) + } + + return bldr.Build() +} + +// Create a MongoCrypt object for benchmarking bulk decryption. +func newBenchmarkCrypt(b *testing.B) *MongoCrypt { + key := []byte{ + 0x9d, 0x94, 0x4b, 0x0d, 0x93, 0xd0, 0xc5, 0x44, + 0xa5, 0x72, 0xfd, 0x32, 0x1b, 0x94, 0x30, 0x90, + 0x23, 0x35, 0x73, 0x7c, 0xf0, 0xf6, 0xc2, 0xf4, + 0xda, 0x23, 0x56, 0xe7, 0x8f, 0x04, 0xcc, 0xfa, + 0xde, 0x75, 0xb4, 0x51, 0x87, 0xf3, 0x8b, 0x97, + 0xd7, 0x4b, 0x44, 0x3b, 0xac, 0x39, 0xa2, 0xc6, + 0x4d, 0x91, 0x00, 0x3e, 0xd1, 0xfa, 0x4a, 0x30, + 0xc1, 0xd2, 0xc6, 0x5e, 0xfb, 0xac, 0x41, 0xf2, + 0x48, 0x13, 0x3c, 0x9b, 0x50, 0xfc, 0xa7, 0x24, + 0x7a, 0x2e, 0x02, 0x63, 0xa3, 0xc6, 0x16, 0x25, + 0x51, 0x50, 0x78, 0x3e, 0x0f, 0xd8, 0x6e, 0x84, + 0xa6, 0xec, 0x8d, 0x2d, 0x24, 0x47, 0xe5, 0xaf} + + localProvider := bsoncore.NewDocumentBuilder(). + AppendBinary("key", 0, key). + Build() + + kmsProviders := bsoncore.NewDocumentBuilder(). + AppendDocument("local", localProvider). + Build() + + cryptOpts := options.MongoCrypt().SetKmsProviders(kmsProviders) + + crypt, err := NewMongoCrypt(cryptOpts) + + require.NoError(b, err) + assert.NotNil(b, crypt) + + return crypt +} + +func BenchmarkBulkDecryption(b *testing.B) { + crypt := newBenchmarkCrypt(b) + defer crypt.Close() + + // Set up the benchmark data: + encryptedDoc := makeFullEncryptBenchmarkDocs(b, crypt, 2) + + repeatDecrypt := func(b *testing.B, dur time.Duration) { + for start := time.Now(); time.Since(start) < dur; { + decryptBenchmarkDoc(b, crypt, encryptedDoc) + } + } + + // Warm up the benchmark + repeatDecrypt(b, time.Second) + + benchmarks := []struct { + threads int + }{ + {threads: 1}, + {threads: 2}, + {threads: 8}, + {threads: 64}, + } + + for _, bench := range benchmarks { + b.Run(fmt.Sprintf("%v threads", bench.threads), func(b *testing.B) { + runtime.GOMAXPROCS(bench.threads) + + b.ResetTimer() + b.ReportAllocs() + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + repeatDecrypt(b, time.Second) + } + }) + }) + } +} diff --git a/x/mongo/driver/mongocrypt/mem.prof b/x/mongo/driver/mongocrypt/mem.prof new file mode 100644 index 0000000000000000000000000000000000000000..bdd54147c40a64c96251af101969c619fc2eda1e GIT binary patch literal 2138 zcmV-g2&MNQiwFP!00004|FlNh%Q)5P!64R6-ll zD6N!KN*b!DX(OdorM42)%-Vp`qL_mqomlU)@AE#-`@XX?`&a<^z`w(FNjQM2ArKCr zAo#-pR3oly!CwkWQRKs~{qhG#Knfxsd}A^A1|!G^2qO}rZ!VIe$dAv=o)EYnzE>x3 zKZJ3Zgy=Wxq$sM!R}Y*Jcs0Bg7I-y8aD;^DTVW}R0{GyQKM{BUKK2Pb0Cl*I)YD78 zSUiT7fBjj)f8l`7UmZvUksrGoq&N!VYj3 z!ogroEea(9$d5saqcA>p=4Bx*0*8H40M)^EK@b6qF=?Yu_y)tM4iY#)+Ua%)Pz0Ym z?b)vvkA_h_bl?usPA4Qlb@<4OKNZDkfX9HxHb5utB#m@jilTaa?3`z$7M}NkFV+!@ z{BYl)>KFcce%4o26|N0O>gwm^B_%)&`09_mWR0*$&^1CA?jr59SBj!WeC)Rz;cj8S~$6c2jsR`E9LNw-;IhKfp_Pcd2 zxaT=k%T?XL+GC-2o~!@Eem7WE6-L7UJje^sgrEBHM@RUuHNj?4fF_WzM0)A46h+PW z_ZL1CiksodfaqH@^x;0zPY(yAC~Cn+T@P=8E1u#OxCh@u`sw$%qgH(NtcSP4N7W*} z74F6Nl79MLwG>5heD$D*$Kh!Yj|0V&^wW2FJjUGQC*T>6KLJB{h%Ba$S4)7}@x|jD51@AF67JhU z#xhwAIjsOPQ&6s(ZN^e|`d#7F+|fymwoe+&tCosh&ylA^y0Nm0~= z|MmCx1>ObEc=27JVwEhRM|~2YZv520Ie!3k!zPiv8B>dWYFNswm!RG}k!AiW6+($P^fO_$< zKYM5|ObfIZR^e6TK3bHbs1INK4PRkF)CWKJRQJJZyqercPjc7&`0Vk^!c{+fyI#2N zhx_sU;z8i1(+5#jLX7i1tn)Hwxug`PbvH)?#-u%hi~`fj!V);Tr1nAWV~vZb=Ej^<3cXc{>)n~_Z`r-PvrB`}bZ-AlcvU&2c5&%>BPY|rkpX#I z+1RRCTA{!SbD8h??(h%@OhHXiV!lGo3S?nG&-(^VW)) z>7du10on1$g{LLz#9bc%u5-iP(|Jc+bIWl+UY9rW_N2P8VqFH?Ga}}Don;oi?o{54 zTMW1wof{`_0IjmIS&e`4R!TH3rLO)ID;e7~WIDLZHjQyzGYn=8$OfBsCd}Q;P#?VQ zwsSs(v!!j1j`#Wh7AAsCI~&HgY~HF_HkYAgr!+%n_#@DuBpfgkKQ77ZS{eQ2_Df3Wu~sXt#}c$jcHk4PyYXy=CFx;@s8`s9WhbQ zp@j(2&C-m}qOPf|kGfgPd-;|wG~bx1my67BMoo*U$=i)mmoFqjE0vg$ozLX0_f-oC z)J==chmA4a%rdV$TPiD0mhIHa1t&elXC$2!gqGL})-FVi$nD9n)|Cxi_O8Wkb)+&$ z{6)ZhiDTyQLR8Q}FRe8&mtS35S?W3ee6=sAi)EvzS@xt>;4f{yN|;rt>+4iJ`GQ9E z;rZkbdT+lw*nBKzn`KL96XyJAsb9S93NGk~%y%2^u<~O(XV_S@N1bVP%cl&-EfvWV z%yu5Se$4iEJUOK{a&mq^bGDWFj;8kA`b0MWXwFo3C?zXDr8!KQ(kx}CS;+E_3pJ-K z%d9A-i^<_+I<<1w-o2S!!+T59!!t?#FIQ3~l$<$~Dd!8>)RGm+q`GWna*2{jCQ~vMp>btSxO Date: Thu, 12 Sep 2024 13:05:28 -0600 Subject: [PATCH 02/10] GODRIVER-2907 Add comment back, remove mem.prof --- x/mongo/driver/mongocrypt/binary.go | 2 +- x/mongo/driver/mongocrypt/mem.prof | Bin 2138 -> 0 bytes 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 x/mongo/driver/mongocrypt/mem.prof diff --git a/x/mongo/driver/mongocrypt/binary.go b/x/mongo/driver/mongocrypt/binary.go index 7abc976457..4e4b51d74b 100644 --- a/x/mongo/driver/mongocrypt/binary.go +++ b/x/mongo/driver/mongocrypt/binary.go @@ -11,7 +11,6 @@ package mongocrypt /* #include -#include // Include for memcpy #include */ import "C" @@ -32,6 +31,7 @@ func newBinary() *binary { } } +// newBinaryFromBytes creates a binary instance from a byte buffer. func newBinaryFromBytes(data []byte) *binary { if len(data) == 0 { return newBinary() diff --git a/x/mongo/driver/mongocrypt/mem.prof b/x/mongo/driver/mongocrypt/mem.prof deleted file mode 100644 index bdd54147c40a64c96251af101969c619fc2eda1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2138 zcmV-g2&MNQiwFP!00004|FlNh%Q)5P!64R6-ll zD6N!KN*b!DX(OdorM42)%-Vp`qL_mqomlU)@AE#-`@XX?`&a<^z`w(FNjQM2ArKCr zAo#-pR3oly!CwkWQRKs~{qhG#Knfxsd}A^A1|!G^2qO}rZ!VIe$dAv=o)EYnzE>x3 zKZJ3Zgy=Wxq$sM!R}Y*Jcs0Bg7I-y8aD;^DTVW}R0{GyQKM{BUKK2Pb0Cl*I)YD78 zSUiT7fBjj)f8l`7UmZvUksrGoq&N!VYj3 z!ogroEea(9$d5saqcA>p=4Bx*0*8H40M)^EK@b6qF=?Yu_y)tM4iY#)+Ua%)Pz0Ym z?b)vvkA_h_bl?usPA4Qlb@<4OKNZDkfX9HxHb5utB#m@jilTaa?3`z$7M}NkFV+!@ z{BYl)>KFcce%4o26|N0O>gwm^B_%)&`09_mWR0*$&^1CA?jr59SBj!WeC)Rz;cj8S~$6c2jsR`E9LNw-;IhKfp_Pcd2 zxaT=k%T?XL+GC-2o~!@Eem7WE6-L7UJje^sgrEBHM@RUuHNj?4fF_WzM0)A46h+PW z_ZL1CiksodfaqH@^x;0zPY(yAC~Cn+T@P=8E1u#OxCh@u`sw$%qgH(NtcSP4N7W*} z74F6Nl79MLwG>5heD$D*$Kh!Yj|0V&^wW2FJjUGQC*T>6KLJB{h%Ba$S4)7}@x|jD51@AF67JhU z#xhwAIjsOPQ&6s(ZN^e|`d#7F+|fymwoe+&tCosh&ylA^y0Nm0~= z|MmCx1>ObEc=27JVwEhRM|~2YZv520Ie!3k!zPiv8B>dWYFNswm!RG}k!AiW6+($P^fO_$< zKYM5|ObfIZR^e6TK3bHbs1INK4PRkF)CWKJRQJJZyqercPjc7&`0Vk^!c{+fyI#2N zhx_sU;z8i1(+5#jLX7i1tn)Hwxug`PbvH)?#-u%hi~`fj!V);Tr1nAWV~vZb=Ej^<3cXc{>)n~_Z`r-PvrB`}bZ-AlcvU&2c5&%>BPY|rkpX#I z+1RRCTA{!SbD8h??(h%@OhHXiV!lGo3S?nG&-(^VW)) z>7du10on1$g{LLz#9bc%u5-iP(|Jc+bIWl+UY9rW_N2P8VqFH?Ga}}Don;oi?o{54 zTMW1wof{`_0IjmIS&e`4R!TH3rLO)ID;e7~WIDLZHjQyzGYn=8$OfBsCd}Q;P#?VQ zwsSs(v!!j1j`#Wh7AAsCI~&HgY~HF_HkYAgr!+%n_#@DuBpfgkKQ77ZS{eQ2_Df3Wu~sXt#}c$jcHk4PyYXy=CFx;@s8`s9WhbQ zp@j(2&C-m}qOPf|kGfgPd-;|wG~bx1my67BMoo*U$=i)mmoFqjE0vg$ozLX0_f-oC z)J==chmA4a%rdV$TPiD0mhIHa1t&elXC$2!gqGL})-FVi$nD9n)|Cxi_O8Wkb)+&$ z{6)ZhiDTyQLR8Q}FRe8&mtS35S?W3ee6=sAi)EvzS@xt>;4f{yN|;rt>+4iJ`GQ9E z;rZkbdT+lw*nBKzn`KL96XyJAsb9S93NGk~%y%2^u<~O(XV_S@N1bVP%cl&-EfvWV z%yu5Se$4iEJUOK{a&mq^bGDWFj;8kA`b0MWXwFo3C?zXDr8!KQ(kx}CS;+E_3pJ-K z%d9A-i^<_+I<<1w-o2S!!+T59!!t?#FIQ3~l$<$~Dd!8>)RGm+q`GWna*2{jCQ~vMp>btSxO Date: Thu, 12 Sep 2024 13:34:11 -0600 Subject: [PATCH 03/10] GODRIVER-2907 Clean up nomenclature and comments --- x/mongo/driver/mongocrypt/binary_test.go | 67 ++++++++++++++--------- x/mongo/driver/mongocrypt/mem.prof | Bin 0 -> 2598 bytes 2 files changed, 40 insertions(+), 27 deletions(-) create mode 100644 x/mongo/driver/mongocrypt/mem.prof diff --git a/x/mongo/driver/mongocrypt/binary_test.go b/x/mongo/driver/mongocrypt/binary_test.go index a424e49d1b..457e97213c 100644 --- a/x/mongo/driver/mongocrypt/binary_test.go +++ b/x/mongo/driver/mongocrypt/binary_test.go @@ -24,7 +24,8 @@ import ( "go.mongodb.org/mongo-driver/v2/x/mongo/driver/mongocrypt/options" ) -func resourceToDocumentB(b *testing.B, filename string) bsoncore.Document { +// load JSON for benchmark +func resourceToDocumentForBench(b *testing.B, filename string) bsoncore.Document { b.Helper() content, err := ioutil.ReadFile(path.Join(resourcesDir, filename)) @@ -38,7 +39,8 @@ func resourceToDocumentB(b *testing.B, filename string) bsoncore.Document { return doc } -func addMongoKeysForBenchmark(b *testing.B, encryptCtx *Context) { +// Add encryption key to the encryption context. +func addMongoKeysForBench(b *testing.B, encryptCtx *Context) { b.Helper() if encryptCtx.State() != NeedMongoKeys { @@ -49,19 +51,18 @@ func addMongoKeysForBenchmark(b *testing.B, encryptCtx *Context) { require.NoError(b, err) // feed result and finish op - err = encryptCtx.AddOperationResult(resourceToDocumentB(b, "local-key-document.json")) + err = encryptCtx.AddOperationResult(resourceToDocumentForBench(b, "local-key-document.json")) require.NoError(b, err) err = encryptCtx.CompleteOperation() require.NoError(b, err) } -// Encrypt 1500 string values of the form "value ". -func encryptBenchmarkDoc(b *testing.B, crypt *MongoCrypt, iter int) bsoncore.Document { +// encrypt a document for benchmarking +func createEncryptedDocForBench(b *testing.B, crypt *MongoCrypt, iter int) bsoncore.Document { b.Helper() const algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" - const numOfKeys = 1500 // create explicit encryption context and check initial state keyID := bson.Binary{ @@ -77,7 +78,7 @@ func encryptBenchmarkDoc(b *testing.B, crypt *MongoCrypt, iter int) bsoncore.Doc defer encryptCtx.Close() - addMongoKeysForBenchmark(b, encryptCtx) + addMongoKeysForBench(b, encryptCtx) // perform final encryption encryptedDoc, err := encryptCtx.Finish() @@ -86,7 +87,8 @@ func encryptBenchmarkDoc(b *testing.B, crypt *MongoCrypt, iter int) bsoncore.Doc return encryptedDoc } -func decryptBenchmarkDoc(b *testing.B, crypt *MongoCrypt, encryptedDoc bsoncore.Document) bsoncore.Document { +// decrypt an encrypted document for benchmarking. +func decryptDocForBench(b *testing.B, crypt *MongoCrypt, encryptedDoc bsoncore.Document) bsoncore.Document { b.Helper() // create explicit decryption context and check initial state @@ -104,11 +106,11 @@ func decryptBenchmarkDoc(b *testing.B, crypt *MongoCrypt, encryptedDoc bsoncore. // create a document of the form: // { "key1": , "key2": , ... } -func makeFullEncryptBenchmarkDocs(b *testing.B, crypt *MongoCrypt, count int) bsoncore.Document { +func createEncryptedDocForBulkDecryptionBench(b *testing.B, crypt *MongoCrypt, count int) bsoncore.Document { bldr := bsoncore.NewDocumentBuilder() for i := 0; i < count; i++ { - encDoc := encryptBenchmarkDoc(b, crypt, i) + encDoc := createEncryptedDocForBench(b, crypt, i) bldr.AppendValue(fmt.Sprintf("key%v", i), encDoc.Lookup("v")) } @@ -116,7 +118,7 @@ func makeFullEncryptBenchmarkDocs(b *testing.B, crypt *MongoCrypt, count int) bs } // Create a MongoCrypt object for benchmarking bulk decryption. -func newBenchmarkCrypt(b *testing.B) *MongoCrypt { +func newCryptForBench(b *testing.B) *MongoCrypt { key := []byte{ 0x9d, 0x94, 0x4b, 0x0d, 0x93, 0xd0, 0xc5, 0x44, 0xa5, 0x72, 0xfd, 0x32, 0x1b, 0x94, 0x30, 0x90, @@ -150,19 +152,26 @@ func newBenchmarkCrypt(b *testing.B) *MongoCrypt { } func BenchmarkBulkDecryption(b *testing.B) { - crypt := newBenchmarkCrypt(b) + const numKeys = 1500 + const repeatCount = 10 + + // Create crypt that uses a data key with the "local" KMS provider. + crypt := newCryptForBench(b) defer crypt.Close() - // Set up the benchmark data: - encryptedDoc := makeFullEncryptBenchmarkDocs(b, crypt, 2) + // Encrypt 1500 string values of the form value 0001, value 0002, value 0003, + // ... with the algorithm AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic. + encryptedDoc := createEncryptedDocForBulkDecryptionBench(b, crypt, numKeys) + // Create a handle to mongocrypt_t, decrypt the document repeatedly for one + // second to warm up the benchmark. repeatDecrypt := func(b *testing.B, dur time.Duration) { for start := time.Now(); time.Since(start) < dur; { - decryptBenchmarkDoc(b, crypt, encryptedDoc) + decryptDocForBench(b, crypt, encryptedDoc) } } - // Warm up the benchmark + // Warm up the benchmark. repeatDecrypt(b, time.Second) benchmarks := []struct { @@ -174,18 +183,22 @@ func BenchmarkBulkDecryption(b *testing.B) { {threads: 64}, } + // Run the benchmark. Repeat benchmark for thread counts: (1, 2, 8, 64). + // Repeat 10 times. for _, bench := range benchmarks { - b.Run(fmt.Sprintf("%v threads", bench.threads), func(b *testing.B) { - runtime.GOMAXPROCS(bench.threads) - - b.ResetTimer() - b.ReportAllocs() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - repeatDecrypt(b, time.Second) - } + for i := 0; i < repeatCount; i++ { + b.Run(fmt.Sprintf("threadCount=%v iter=%v", bench.threads, i), func(b *testing.B) { + runtime.GOMAXPROCS(bench.threads) + + b.ResetTimer() + b.ReportAllocs() + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + repeatDecrypt(b, time.Second) + } + }) }) - }) + } } } diff --git a/x/mongo/driver/mongocrypt/mem.prof b/x/mongo/driver/mongocrypt/mem.prof new file mode 100644 index 0000000000000000000000000000000000000000..c57dbb7a2f87113dc7cd6a491a2ce7deb8ae285a GIT binary patch literal 2598 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 IIyn~r0Atr5mH+?% literal 0 HcmV?d00001 From 4982141eb6457459e87b0419a33b3fbea796e0e2 Mon Sep 17 00:00:00 2001 From: Preston Vasquez Date: Thu, 12 Sep 2024 14:16:24 -0600 Subject: [PATCH 04/10] GODRIVER-2907 no timed run --- x/mongo/driver/mongocrypt/binary_test.go | 33 ++++++++++++----------- x/mongo/driver/mongocrypt/mem.prof | Bin 2598 -> 0 bytes 2 files changed, 18 insertions(+), 15 deletions(-) delete mode 100644 x/mongo/driver/mongocrypt/mem.prof diff --git a/x/mongo/driver/mongocrypt/binary_test.go b/x/mongo/driver/mongocrypt/binary_test.go index 457e97213c..cb72179878 100644 --- a/x/mongo/driver/mongocrypt/binary_test.go +++ b/x/mongo/driver/mongocrypt/binary_test.go @@ -163,17 +163,11 @@ func BenchmarkBulkDecryption(b *testing.B) { // ... with the algorithm AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic. encryptedDoc := createEncryptedDocForBulkDecryptionBench(b, crypt, numKeys) - // Create a handle to mongocrypt_t, decrypt the document repeatedly for one - // second to warm up the benchmark. - repeatDecrypt := func(b *testing.B, dur time.Duration) { - for start := time.Now(); time.Since(start) < dur; { - decryptDocForBench(b, crypt, encryptedDoc) - } + // decrypt the document repeatedly for one to warm up the benchmark. + for start := time.Now(); time.Since(start) < time.Second; { + decryptDocForBench(b, crypt, encryptedDoc) } - // Warm up the benchmark. - repeatDecrypt(b, time.Second) - benchmarks := []struct { threads int }{ @@ -186,19 +180,28 @@ func BenchmarkBulkDecryption(b *testing.B) { // Run the benchmark. Repeat benchmark for thread counts: (1, 2, 8, 64). // Repeat 10 times. for _, bench := range benchmarks { - for i := 0; i < repeatCount; i++ { - b.Run(fmt.Sprintf("threadCount=%v iter=%v", bench.threads, i), func(b *testing.B) { - runtime.GOMAXPROCS(bench.threads) + var totalOpsPerSec float64 + + b.Run(fmt.Sprintf("threadCount=%v", bench.threads), func(b *testing.B) { + runtime.GOMAXPROCS(bench.threads) + for i := 0; i < repeatCount; i++ { b.ResetTimer() b.ReportAllocs() + startTime := time.Now() + b.RunParallel(func(pb *testing.PB) { for pb.Next() { - repeatDecrypt(b, time.Second) + decryptDocForBench(b, crypt, encryptedDoc) } }) - }) - } + + totalOpsPerSec += float64(b.N) / time.Now().Sub(startTime).Seconds() + } + }) + + avgOpsPerSec := totalOpsPerSec / float64(repeatCount) + b.Logf("thread count: %v, ops/sec: %.2f\n", bench.threads, avgOpsPerSec) } } diff --git a/x/mongo/driver/mongocrypt/mem.prof b/x/mongo/driver/mongocrypt/mem.prof deleted file mode 100644 index c57dbb7a2f87113dc7cd6a491a2ce7deb8ae285a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2598 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 IIyn~r0Atr5mH+?% From 7314d93ea20ed87c2664d2336f90c0ddd98992f4 Mon Sep 17 00:00:00 2001 From: Preston Vasquez Date: Thu, 12 Sep 2024 14:19:58 -0600 Subject: [PATCH 05/10] GODRIVER-2907 Remove ioutil refn --- x/mongo/driver/mongocrypt/binary_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/mongo/driver/mongocrypt/binary_test.go b/x/mongo/driver/mongocrypt/binary_test.go index cb72179878..5d764d1554 100644 --- a/x/mongo/driver/mongocrypt/binary_test.go +++ b/x/mongo/driver/mongocrypt/binary_test.go @@ -11,7 +11,7 @@ package mongocrypt import ( "fmt" - "io/ioutil" + "os" "path" "runtime" "testing" @@ -28,7 +28,7 @@ import ( func resourceToDocumentForBench(b *testing.B, filename string) bsoncore.Document { b.Helper() - content, err := ioutil.ReadFile(path.Join(resourcesDir, filename)) + content, err := os.ReadFile(path.Join(resourcesDir, filename)) require.NoError(b, err) var doc bsoncore.Document From 5229d78ecfcd13f2cfd13327bf3b74da35da3b1e Mon Sep 17 00:00:00 2001 From: Preston Vasquez Date: Mon, 16 Sep 2024 09:14:28 -0600 Subject: [PATCH 06/10] GODRIVER-2907 Fix typo --- x/mongo/driver/mongocrypt/binary_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/mongo/driver/mongocrypt/binary_test.go b/x/mongo/driver/mongocrypt/binary_test.go index 5d764d1554..6431d9c9c6 100644 --- a/x/mongo/driver/mongocrypt/binary_test.go +++ b/x/mongo/driver/mongocrypt/binary_test.go @@ -163,7 +163,7 @@ func BenchmarkBulkDecryption(b *testing.B) { // ... with the algorithm AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic. encryptedDoc := createEncryptedDocForBulkDecryptionBench(b, crypt, numKeys) - // decrypt the document repeatedly for one to warm up the benchmark. + // decrypt the document repeatedly for one second to warm up the benchmark. for start := time.Now(); time.Since(start) < time.Second; { decryptDocForBench(b, crypt, encryptedDoc) } From e84b495b6f38fec21c9d8d3a3d6cc0f33e5eaa18 Mon Sep 17 00:00:00 2001 From: Preston Vasquez Date: Tue, 17 Sep 2024 10:35:43 -0600 Subject: [PATCH 07/10] Update x/mongo/driver/mongocrypt/binary_test.go Co-authored-by: Kevin Albertson --- x/mongo/driver/mongocrypt/binary_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/mongo/driver/mongocrypt/binary_test.go b/x/mongo/driver/mongocrypt/binary_test.go index 6431d9c9c6..767ddec537 100644 --- a/x/mongo/driver/mongocrypt/binary_test.go +++ b/x/mongo/driver/mongocrypt/binary_test.go @@ -71,7 +71,7 @@ func createEncryptedDocForBench(b *testing.B, crypt *MongoCrypt, iter int) bsonc } encryptOpts := options.ExplicitEncryption().SetAlgorithm(algorithm).SetKeyID(keyID) - doc := bsoncore.NewDocumentBuilder().AppendString("v", fmt.Sprintf("value %v", iter)).Build() + doc := bsoncore.NewDocumentBuilder().AppendString("v", fmt.Sprintf("value %04v", iter)).Build() encryptCtx, err := crypt.CreateExplicitEncryptionContext(doc, encryptOpts) require.NoError(b, err) From 167b86dd2a3b7cac74e19be8bd4504314e7821ed Mon Sep 17 00:00:00 2001 From: Preston Vasquez Date: Tue, 17 Sep 2024 10:35:49 -0600 Subject: [PATCH 08/10] Update x/mongo/driver/mongocrypt/binary_test.go Co-authored-by: Kevin Albertson --- x/mongo/driver/mongocrypt/binary_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/mongo/driver/mongocrypt/binary_test.go b/x/mongo/driver/mongocrypt/binary_test.go index 767ddec537..7815df4e56 100644 --- a/x/mongo/driver/mongocrypt/binary_test.go +++ b/x/mongo/driver/mongocrypt/binary_test.go @@ -111,7 +111,7 @@ func createEncryptedDocForBulkDecryptionBench(b *testing.B, crypt *MongoCrypt, c for i := 0; i < count; i++ { encDoc := createEncryptedDocForBench(b, crypt, i) - bldr.AppendValue(fmt.Sprintf("key%v", i), encDoc.Lookup("v")) + bldr.AppendValue(fmt.Sprintf("key%04v", i), encDoc.Lookup("v")) } return bldr.Build() From 58eea79681b7fcdad6b0c4d03ae68c7d1c0ee373 Mon Sep 17 00:00:00 2001 From: Preston Vasquez Date: Tue, 17 Sep 2024 10:35:55 -0600 Subject: [PATCH 09/10] Update x/mongo/driver/mongocrypt/binary_test.go Co-authored-by: Kevin Albertson --- x/mongo/driver/mongocrypt/binary_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/mongo/driver/mongocrypt/binary_test.go b/x/mongo/driver/mongocrypt/binary_test.go index 7815df4e56..d233afcf0f 100644 --- a/x/mongo/driver/mongocrypt/binary_test.go +++ b/x/mongo/driver/mongocrypt/binary_test.go @@ -105,7 +105,7 @@ func decryptDocForBench(b *testing.B, crypt *MongoCrypt, encryptedDoc bsoncore.D } // create a document of the form: -// { "key1": , "key2": , ... } +// { "key0001": , "key0002": , ... } func createEncryptedDocForBulkDecryptionBench(b *testing.B, crypt *MongoCrypt, count int) bsoncore.Document { bldr := bsoncore.NewDocumentBuilder() From 8f56eee20cdb66afafcdc3be7a11be9e8bfd3049 Mon Sep 17 00:00:00 2001 From: Preston Vasquez Date: Tue, 17 Sep 2024 10:38:45 -0600 Subject: [PATCH 10/10] GODRIVER-2907 Use median ops/sec --- x/mongo/driver/mongocrypt/binary_test.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/x/mongo/driver/mongocrypt/binary_test.go b/x/mongo/driver/mongocrypt/binary_test.go index d233afcf0f..6f122745d4 100644 --- a/x/mongo/driver/mongocrypt/binary_test.go +++ b/x/mongo/driver/mongocrypt/binary_test.go @@ -14,6 +14,7 @@ import ( "os" "path" "runtime" + "sort" "testing" "time" @@ -151,6 +152,17 @@ func newCryptForBench(b *testing.B) *MongoCrypt { return crypt } +func calcMedian(values []float64) float64 { + sort.Float64s(values) + + n := len(values) + if n%2 == 0 { + return (values[n/2-1] + values[n/2]) / 2.0 + } + + return values[(n-1)/2] +} + func BenchmarkBulkDecryption(b *testing.B) { const numKeys = 1500 const repeatCount = 10 @@ -180,7 +192,7 @@ func BenchmarkBulkDecryption(b *testing.B) { // Run the benchmark. Repeat benchmark for thread counts: (1, 2, 8, 64). // Repeat 10 times. for _, bench := range benchmarks { - var totalOpsPerSec float64 + var opsPerSec []float64 b.Run(fmt.Sprintf("threadCount=%v", bench.threads), func(b *testing.B) { runtime.GOMAXPROCS(bench.threads) @@ -197,11 +209,10 @@ func BenchmarkBulkDecryption(b *testing.B) { } }) - totalOpsPerSec += float64(b.N) / time.Now().Sub(startTime).Seconds() + opsPerSec = append(opsPerSec, float64(b.N)/time.Now().Sub(startTime).Seconds()) } }) - avgOpsPerSec := totalOpsPerSec / float64(repeatCount) - b.Logf("thread count: %v, ops/sec: %.2f\n", bench.threads, avgOpsPerSec) + b.Logf("thread count: %v, median ops/sec: %.2f\n", bench.threads, calcMedian(opsPerSec)) } }