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) } } }) }) } }