|  | @@ -7,127 +7,117 @@ import (
 | 
	
		
			
				|  |  |  	googleMessage2 "./tmp/datasets/google_message2"
 | 
	
		
			
				|  |  |  	googleMessage3 "./tmp/datasets/google_message3"
 | 
	
		
			
				|  |  |  	googleMessage4 "./tmp/datasets/google_message4"
 | 
	
		
			
				|  |  | -	"errors"
 | 
	
		
			
				|  |  |  	"flag"
 | 
	
		
			
				|  |  |  	"github.com/golang/protobuf/proto"
 | 
	
		
			
				|  |  |  	"io/ioutil"
 | 
	
		
			
				|  |  | -	"os"
 | 
	
		
			
				|  |  |  	"testing"
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // Data is returned by the Load function.
 | 
	
		
			
				|  |  | -type Data struct {
 | 
	
		
			
				|  |  | -	// marshaled is a slice of marshaled protocol
 | 
	
		
			
				|  |  | -	// buffers. 1:1 with unmarshaled.
 | 
	
		
			
				|  |  | -	marshaled [][]byte
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	// Unmarshaled is a slice of unmarshaled protocol
 | 
	
		
			
				|  |  | -	// buffers. 1:1 with marshaled.
 | 
	
		
			
				|  |  | +type Dataset struct {
 | 
	
		
			
				|  |  | +	name        string
 | 
	
		
			
				|  |  | +	newMessage  func() proto.Message
 | 
	
		
			
				|  |  | +	marshaled   [][]byte
 | 
	
		
			
				|  |  |  	unmarshaled []proto.Message
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	count int
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -var data *Data
 | 
	
		
			
				|  |  | -var counter int
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -type GetDefaultInstanceFunction func() proto.Message
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -var getDefaultInstance GetDefaultInstanceFunction
 | 
	
		
			
				|  |  | +var datasets []Dataset
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // This is used to getDefaultInstance for a message type.
 | 
	
		
			
				|  |  | -func generateGetDefaltInstanceFunction(dataset benchmarkWrapper.BenchmarkDataset) error {
 | 
	
		
			
				|  |  | +func generateNewMessageFunction(dataset benchmarkWrapper.BenchmarkDataset) func() proto.Message {
 | 
	
		
			
				|  |  |  	switch dataset.MessageName {
 | 
	
		
			
				|  |  |  	case "benchmarks.proto3.GoogleMessage1":
 | 
	
		
			
				|  |  | -		getDefaultInstance = func() proto.Message { return &googleMessage1Proto3.GoogleMessage1{} }
 | 
	
		
			
				|  |  | -		return nil
 | 
	
		
			
				|  |  | +		return func() proto.Message { return new(googleMessage1Proto3.GoogleMessage1) }
 | 
	
		
			
				|  |  |  	case "benchmarks.proto2.GoogleMessage1":
 | 
	
		
			
				|  |  | -		getDefaultInstance = func() proto.Message { return &googleMessage1Proto2.GoogleMessage1{} }
 | 
	
		
			
				|  |  | -		return nil
 | 
	
		
			
				|  |  | +		return func() proto.Message { return new(googleMessage1Proto2.GoogleMessage1) }
 | 
	
		
			
				|  |  |  	case "benchmarks.proto2.GoogleMessage2":
 | 
	
		
			
				|  |  | -		getDefaultInstance = func() proto.Message { return &googleMessage2.GoogleMessage2{} }
 | 
	
		
			
				|  |  | -		return nil
 | 
	
		
			
				|  |  | +		return func() proto.Message { return new(googleMessage2.GoogleMessage2) }
 | 
	
		
			
				|  |  |  	case "benchmarks.google_message3.GoogleMessage3":
 | 
	
		
			
				|  |  | -		getDefaultInstance = func() proto.Message { return &googleMessage3.GoogleMessage3{} }
 | 
	
		
			
				|  |  | -		return nil
 | 
	
		
			
				|  |  | +		return func() proto.Message { return new(googleMessage3.GoogleMessage3) }
 | 
	
		
			
				|  |  |  	case "benchmarks.google_message4.GoogleMessage4":
 | 
	
		
			
				|  |  | -		getDefaultInstance = func() proto.Message { return &googleMessage4.GoogleMessage4{} }
 | 
	
		
			
				|  |  | -		return nil
 | 
	
		
			
				|  |  | +		return func() proto.Message { return new(googleMessage4.GoogleMessage4) }
 | 
	
		
			
				|  |  |  	default:
 | 
	
		
			
				|  |  | -		return errors.New("Unknown message type: " + dataset.MessageName)
 | 
	
		
			
				|  |  | +		panic("Unknown message type: " + dataset.MessageName)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func TestMain(m *testing.M) {
 | 
	
		
			
				|  |  | +func init() {
 | 
	
		
			
				|  |  |  	flag.Parse()
 | 
	
		
			
				|  |  | -	data = new(Data)
 | 
	
		
			
				|  |  | -	rawData, err := ioutil.ReadFile(flag.Arg(0))
 | 
	
		
			
				|  |  | -	if err != nil {
 | 
	
		
			
				|  |  | -		panic("Couldn't find file" + flag.Arg(0))
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	var dataset benchmarkWrapper.BenchmarkDataset
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	if err = proto.Unmarshal(rawData, &dataset); err != nil {
 | 
	
		
			
				|  |  | -		panic("The raw input data can't be parse into BenchmarkDataset message.")
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	generateGetDefaltInstanceFunction(dataset)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	for _, payload := range dataset.Payload {
 | 
	
		
			
				|  |  | -		data.marshaled = append(data.marshaled, payload)
 | 
	
		
			
				|  |  | -		m := getDefaultInstance()
 | 
	
		
			
				|  |  | -		proto.Unmarshal(payload, m)
 | 
	
		
			
				|  |  | -		data.unmarshaled = append(data.unmarshaled, m)
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	data.count = len(data.unmarshaled)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	os.Exit(m.Run())
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func BenchmarkUnmarshal(b *testing.B) {
 | 
	
		
			
				|  |  | -	b.ReportAllocs()
 | 
	
		
			
				|  |  | -	for i := 0; i < b.N; i++ {
 | 
	
		
			
				|  |  | -		payload := data.marshaled[counter%data.count]
 | 
	
		
			
				|  |  | -		out := getDefaultInstance()
 | 
	
		
			
				|  |  | -		if err := proto.Unmarshal(payload, out); err != nil {
 | 
	
		
			
				|  |  | -			b.Fatalf("can't unmarshal message %d %v", counter%data.count, err)
 | 
	
		
			
				|  |  | +	for _, f := range flag.Args() {
 | 
	
		
			
				|  |  | +		// Load the benchmark.
 | 
	
		
			
				|  |  | +		b, err := ioutil.ReadFile(f)
 | 
	
		
			
				|  |  | +		if err != nil {
 | 
	
		
			
				|  |  | +			panic(err)
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -		counter++
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func BenchmarkMarshal(b *testing.B) {
 | 
	
		
			
				|  |  | -	b.ReportAllocs()
 | 
	
		
			
				|  |  | -	for i := 0; i < b.N; i++ {
 | 
	
		
			
				|  |  | -		m := data.unmarshaled[counter%data.count]
 | 
	
		
			
				|  |  | -		if _, err := proto.Marshal(m); err != nil {
 | 
	
		
			
				|  |  | -			b.Fatalf("can't marshal message %d %+v: %v", counter%data.count, m, err)
 | 
	
		
			
				|  |  | +		// Parse the benchmark.
 | 
	
		
			
				|  |  | +		var dm benchmarkWrapper.BenchmarkDataset
 | 
	
		
			
				|  |  | +		if err := proto.Unmarshal(b, &dm); err != nil {
 | 
	
		
			
				|  |  | +			panic(err)
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -		counter++
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func BenchmarkSize(b *testing.B) {
 | 
	
		
			
				|  |  | -	b.ReportAllocs()
 | 
	
		
			
				|  |  | -	for i := 0; i < b.N; i++ {
 | 
	
		
			
				|  |  | -		proto.Size(data.unmarshaled[counter%data.count])
 | 
	
		
			
				|  |  | -		counter++
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | +		// 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
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func BenchmarkClone(b *testing.B) {
 | 
	
		
			
				|  |  | -	b.ReportAllocs()
 | 
	
		
			
				|  |  | -	for i := 0; i < b.N; i++ {
 | 
	
		
			
				|  |  | -		proto.Clone(data.unmarshaled[counter%data.count])
 | 
	
		
			
				|  |  | -		counter++
 | 
	
		
			
				|  |  | +		datasets = append(datasets, ds)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func BenchmarkMerge(b *testing.B) {
 | 
	
		
			
				|  |  | -	b.ReportAllocs()
 | 
	
		
			
				|  |  | -	for i := 0; i < b.N; i++ {
 | 
	
		
			
				|  |  | -		out := getDefaultInstance()
 | 
	
		
			
				|  |  | -		proto.Merge(out, data.unmarshaled[counter%data.count])
 | 
	
		
			
				|  |  | -		counter++
 | 
	
		
			
				|  |  | +func Benchmark(b *testing.B) {
 | 
	
		
			
				|  |  | +	for _, ds := range datasets {
 | 
	
		
			
				|  |  | +		b.Run(ds.name, func(b *testing.B) {
 | 
	
		
			
				|  |  | +			counter := 0
 | 
	
		
			
				|  |  | +			count := len(ds.marshaled)
 | 
	
		
			
				|  |  | +			b.Run("Unmarshal", func(b *testing.B) {
 | 
	
		
			
				|  |  | +				for i := 0; i < b.N; i++ {
 | 
	
		
			
				|  |  | +					payload := ds.marshaled[counter%count]
 | 
	
		
			
				|  |  | +					out := ds.newMessage()
 | 
	
		
			
				|  |  | +					if err := proto.Unmarshal(payload, out); err != nil {
 | 
	
		
			
				|  |  | +						b.Fatalf("can't unmarshal message %d %v", counter%count, err)
 | 
	
		
			
				|  |  | +					}
 | 
	
		
			
				|  |  | +					counter++
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +			})
 | 
	
		
			
				|  |  | +			b.Run("Marshal", func(b *testing.B) {
 | 
	
		
			
				|  |  | +				for i := 0; i < b.N; i++ {
 | 
	
		
			
				|  |  | +					m := ds.unmarshaled[counter%count]
 | 
	
		
			
				|  |  | +					if _, err := proto.Marshal(m); err != nil {
 | 
	
		
			
				|  |  | +						b.Fatalf("can't marshal message %d %+v: %v", counter%count, m, err)
 | 
	
		
			
				|  |  | +					}
 | 
	
		
			
				|  |  | +					counter++
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +			})
 | 
	
		
			
				|  |  | +			b.Run("Size", func(b *testing.B) {
 | 
	
		
			
				|  |  | +				for i := 0; i < b.N; i++ {
 | 
	
		
			
				|  |  | +					proto.Size(ds.unmarshaled[counter%count])
 | 
	
		
			
				|  |  | +					counter++
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +			})
 | 
	
		
			
				|  |  | +			b.Run("Clone", func(b *testing.B) {
 | 
	
		
			
				|  |  | +				for i := 0; i < b.N; i++ {
 | 
	
		
			
				|  |  | +					proto.Clone(ds.unmarshaled[counter%count])
 | 
	
		
			
				|  |  | +					counter++
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +			})
 | 
	
		
			
				|  |  | +			b.Run("Merge", func(b *testing.B) {
 | 
	
		
			
				|  |  | +				for i := 0; i < b.N; i++ {
 | 
	
		
			
				|  |  | +					out := ds.newMessage()
 | 
	
		
			
				|  |  | +					proto.Merge(out, ds.unmarshaled[counter%count])
 | 
	
		
			
				|  |  | +					counter++
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +			})
 | 
	
		
			
				|  |  | +		})
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 |