-
Type: Improvement
-
Resolution: Done
-
Priority: Major - P3
-
None
-
Affects Version/s: 1.0.3
-
Component/s: Wire Protocol
-
None
I was doing some performance tests of my app - in golang, using mongo-driver.
I've seen my app spent lots of time in decodeCommandOpMsg function.
After further investigation I've realized that decodeCommandOpMsg does decode full bson payload (all the way down) just to merge wiremessage sections toghether and return back as binary data (mainDoc.UnmarshalBSON and then mainDoc.MarshalBSON back again).
My theory is that it doesn't need to bother about internal structure of a document whatsoever - just merge top-level fields.
I've written simple benchmark and it seems it can be speeded up by the order of magnitude.
You can see benchmarks code here: https://github.com/g2a-com/mongo-go-driver/commit/1cf2b874b5f8dd022c2b7aed7e9090256eb335d8?diff=unified
And a proof of concept of the improvement here: https://github.com/g2a-com/mongo-go-driver/commit/deeacb2e7aa5e9cd7820c52b4f945fdc5d09be52
Results - without a change:
root@d705c9e30444:/go/src/go.mongodb.org/mongo-driver# go test -benchmem -bench=BenchmarkReadOpMsg ./benchmark goos: linux goarch: amd64 pkg: go.mongodb.org/mongo-driver/benchmark BenchmarkReadOpMsgFlatDecoding-2 20000 89926 ns/op 95792 B/op 609 allocs/op BenchmarkReadOpMsgDeepDecoding-2 10000 107868 ns/op 50503 B/op 1185 allocs/op PASS ok go.mongodb.org/mongo-driver/benchmark 3.803s
Results - without my change (https://github.com/g2a-com/mongo-go-driver/commit/deeacb2e7aa5e9cd7820c52b4f945fdc5d09be52):
root@d705c9e30444:/go/src/go.mongodb.org/mongo-driver# go test -benchmem -bench=BenchmarkReadOpMsg ./benchmark goos: linux goarch: amd64 pkg: go.mongodb.org/mongo-driver/benchmark BenchmarkReadOpMsgFlatDecoding-2 500000 2993 ns/op 6464 B/op 15 allocs/op BenchmarkReadOpMsgDeepDecoding-2 1000000 1947 ns/op 2368 B/op 15 allocs/op PASS ok go.mongodb.org/mongo-driver/benchmark 4.516s
Fun fact is that without my change in most cases documents returned from mongodb would be unmarshaled twice - once in decodeCommandOpMsg and 2nd time when driver's user wants to read his data (e.g. by cursor.Unmarshal).
Any thoughts?