Uploaded image for project: 'Go Driver'
  1. Go Driver
  2. GODRIVER-1142

Improve decodeCommandOpMsg performance

    • Type: Icon: Improvement Improvement
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 1.0.3
    • Component/s: Wire Protocol
    • Labels:
      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?

            Assignee:
            kris.brandow@mongodb.com Kristofer Brandow (Inactive)
            Reporter:
            lmarszal Łukasz Marszał
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: