|  | package main | 
|  |  | 
|  | import ( | 
|  | benchmarkWrapper "../tmp" | 
|  | googleMessage1Proto2 "../tmp/datasets/google_message1/proto2" | 
|  | googleMessage1Proto3 "../tmp/datasets/google_message1/proto3" | 
|  | googleMessage2 "../tmp/datasets/google_message2" | 
|  | googleMessage3 "../tmp/datasets/google_message3" | 
|  | googleMessage4 "../tmp/datasets/google_message4" | 
|  | "flag" | 
|  | "github.com/golang/protobuf/proto" | 
|  | "io/ioutil" | 
|  | "testing" | 
|  | ) | 
|  |  | 
|  | // Data is returned by the Load function. | 
|  | type Dataset struct { | 
|  | name        string | 
|  | newMessage  func() proto.Message | 
|  | marshaled   [][]byte | 
|  | unmarshaled []proto.Message | 
|  | } | 
|  |  | 
|  | var datasets []Dataset | 
|  |  | 
|  | // This is used to getDefaultInstance for a message type. | 
|  | func generateNewMessageFunction(dataset benchmarkWrapper.BenchmarkDataset) func() proto.Message { | 
|  | switch dataset.MessageName { | 
|  | case "benchmarks.proto3.GoogleMessage1": | 
|  | return func() proto.Message { return new(googleMessage1Proto3.GoogleMessage1) } | 
|  | case "benchmarks.proto2.GoogleMessage1": | 
|  | return func() proto.Message { return new(googleMessage1Proto2.GoogleMessage1) } | 
|  | case "benchmarks.proto2.GoogleMessage2": | 
|  | return func() proto.Message { return new(googleMessage2.GoogleMessage2) } | 
|  | case "benchmarks.google_message3.GoogleMessage3": | 
|  | return func() proto.Message { return new(googleMessage3.GoogleMessage3) } | 
|  | case "benchmarks.google_message4.GoogleMessage4": | 
|  | return func() proto.Message { return new(googleMessage4.GoogleMessage4) } | 
|  | default: | 
|  | panic("Unknown message type: " + dataset.MessageName) | 
|  | } | 
|  | } | 
|  |  | 
|  | func init() { | 
|  | flag.Parse() | 
|  | for _, f := range flag.Args() { | 
|  | // Load the benchmark. | 
|  | b, err := ioutil.ReadFile(f) | 
|  | if err != nil { | 
|  | panic(err) | 
|  | } | 
|  |  | 
|  | // Parse the benchmark. | 
|  | var dm benchmarkWrapper.BenchmarkDataset | 
|  | if err := proto.Unmarshal(b, &dm); err != nil { | 
|  | panic(err) | 
|  | } | 
|  |  | 
|  | // Determine the concrete protobuf message type to use. | 
|  | var ds Dataset | 
|  | ds.newMessage = generateNewMessageFunction(dm) | 
|  |  | 
|  | // Unmarshal each test message. | 
|  | for _, payload := range dm.Payload { | 
|  | ds.marshaled = append(ds.marshaled, payload) | 
|  | m := ds.newMessage() | 
|  | if err := proto.Unmarshal(payload, m); err != nil { | 
|  | panic(err) | 
|  | } | 
|  | ds.unmarshaled = append(ds.unmarshaled, m) | 
|  | } | 
|  | ds.name = f | 
|  |  | 
|  | datasets = append(datasets, ds) | 
|  | } | 
|  | } | 
|  |  | 
|  | func Benchmark(b *testing.B) { | 
|  | for _, ds := range datasets { | 
|  | b.Run(ds.name, func(b *testing.B) { | 
|  | b.Run("Unmarshal", func(b *testing.B) { | 
|  | for i := 0; i < b.N; i++ { | 
|  | for j, payload := range ds.marshaled { | 
|  | out := ds.newMessage() | 
|  | if err := proto.Unmarshal(payload, out); err != nil { | 
|  | b.Fatalf("can't unmarshal message %d %v", j, err) | 
|  | } | 
|  | } | 
|  | } | 
|  | }) | 
|  | b.Run("Marshal", func(b *testing.B) { | 
|  | for i := 0; i < b.N; i++ { | 
|  | for j, m := range ds.unmarshaled { | 
|  | if _, err := proto.Marshal(m); err != nil { | 
|  | b.Fatalf("can't marshal message %d %+v: %v", j, m, err) | 
|  | } | 
|  | } | 
|  | } | 
|  | }) | 
|  | b.Run("Size", func(b *testing.B) { | 
|  | for i := 0; i < b.N; i++ { | 
|  | for _, m := range ds.unmarshaled { | 
|  | proto.Size(m) | 
|  | } | 
|  | } | 
|  | }) | 
|  | b.Run("Clone", func(b *testing.B) { | 
|  | for i := 0; i < b.N; i++ { | 
|  | for _, m := range ds.unmarshaled { | 
|  | proto.Clone(m) | 
|  | } | 
|  | } | 
|  | }) | 
|  | b.Run("Merge", func(b *testing.B) { | 
|  | for i := 0; i < b.N; i++ { | 
|  | for _, m := range ds.unmarshaled { | 
|  | out := ds.newMessage() | 
|  | proto.Merge(out, m) | 
|  | } | 
|  | } | 
|  | }) | 
|  | }) | 
|  | } | 
|  | } |