blob: 31f2c5aa949b359defc7206f244280e5cdee2f94 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package internal
// This module contains performance benchmarks.
// Run with
// jiri go test -bench . v.io/v23/vom/internal
// The following are the results of a typical run on a desktop machine on 2015/08/04,
// together with the results from comparable tests using protocol buffers in
// C++ and Go on the same machine.
//
// Allocations per vom.Encode : 572
// Allocations per vom.Decode : 405
// Allocations per vom.Encoder.Encode (1 Customer) : 572
// Allocations per vom.Encoder.Encode (1000 Customers): 74508
// Allocations per vom.Decoder.Decode (1 Customer) : 4469
// Allocations per vom.Decoder.Decode (1000 Customers): 405068
// Allocations per gob.Encoder.Encode (1 Customer) : 54
// Allocations per gob.Encoder.Encode (1000 Customers): 3066
// Allocations per gob.Decoder.Decode (1 Customer) : 523
// Allocations per gob.Decoder.Decode (1000 Customers): 14511
//
// BenchmarkVomEncodeCustomer 10000 143809 ns/op
// BenchmarkVomDecodeCustomer 20000 89189 ns/op
// BenchmarkVomEncoder1Customer 10000 135640 ns/op
// BenchmarkVomEncoder1000Customer 100 15527851 ns/op
// BenchmarkVomDecoder1Customer 2000 832101 ns/op
// BenchmarkVomDecoder1000Customer 20 74767365 ns/op
// BenchmarkGobEncoder1Customer 50000 26574 ns/op
// BenchmarkGobEncoder1000Customer 500 3792072 ns/op
// BenchmarkGobDecoder1Customer 20000 93381 ns/op
// BenchmarkGobDecoder1000Customer 500 3604404 ns/op
//
// C++ Protocol buffer encode (1 Customer) 83 ns/op
// C++ Protocol buffer decode (1 Customer) 168 ns/op
// Go Protocol buffer encode (1 Customer) 2191 ns/op
// Go Protocol buffer decode (1 Customer) 3150 ns/op
import "bytes"
import "encoding/gob"
import "fmt"
import "testing"
import "v.io/v23/vom"
// customer is the record we encode and decode during tests.
var customer Customer = Customer{
Name: "John Smith",
Id: 1,
Active: true,
Address: AddressInfo{
Street: "1 Main St.",
City: "Palo Alto",
State: "CA",
Zip: "94303",
},
Credit: CreditReport{
Agency: CreditAgencyEquifax,
Report: AgencyReportEquifaxReport{EquifaxCreditReport{'A'}},
},
}
// ------------------------------------
// vom.Encode benchmarking
func vomEncode(t testing.TB) {
buf, err := vom.Encode(customer)
if err != nil || len(buf) == 0 {
t.Fatalf("vom.Enecode failed: %v", err)
}
}
func TestVomEncodeCustomer(t *testing.T) {
fmt.Printf("Allocations per vom.Encode : %6.0f\n",
testing.AllocsPerRun(10, func() { vomEncode(t) }))
}
func BenchmarkVomEncodeCustomer(b *testing.B) {
for i := 0; i != b.N; i++ {
vomEncode(b)
}
}
// ------------------------------------
// vom.Decode benchmarking
func vomDecode(t testing.TB, buf []byte) {
var c Customer
err := vom.Decode(buf, &c)
if err != nil {
t.Fatalf("vom.Decode failed: %v", err)
}
}
func TestVomDecodeCustomer(t *testing.T) {
buf, err := vom.Encode(customer)
if err != nil || len(buf) == 0 {
t.Fatalf("vom.Encode failed: %v", err)
}
fmt.Printf("Allocations per vom.Decode : %6.0f\n",
testing.AllocsPerRun(10, func() { vomDecode(t, buf) }))
}
func BenchmarkVomDecodeCustomer(b *testing.B) {
buf, err := vom.Encode(customer)
if err != nil || len(buf) == 0 {
b.Fatalf("vom.Encode failed")
}
b.ResetTimer()
for i := 0; i != b.N; i++ {
vomDecode(b, buf)
}
}
// ------------------------------------
// vom.Encoder.Encode benchmarking
func vomEncoderEncode(t testing.TB, n int) {
var buf bytes.Buffer
encoder := vom.NewEncoder(&buf)
for j := 0; j != n; j++ {
err := encoder.Encode(customer)
if err != nil {
t.Fatalf("encoder.Encode failed: %v", err)
}
}
}
func TestVomEncoder(t *testing.T) {
fmt.Printf("Allocations per vom.Encoder.Encode (1 Customer) : %6.0f\n",
testing.AllocsPerRun(10, func() { vomEncoderEncode(t, 1) }))
fmt.Printf("Allocations per vom.Encoder.Encode (1000 Customers): %6.0f\n",
testing.AllocsPerRun(10, func() { vomEncoderEncode(t, 1000) }))
fmt.Printf("Allocations per vom.Encoder.Encode (1000 RawValues): %6.0f\n",
testing.AllocsPerRun(10, func() { vomEncoderEncodeRawValue(t, 1000, makeCustomerRawValue(t)) }))
}
func BenchmarkVomEncoder1Customer(b *testing.B) {
for i := 0; i != b.N; i++ {
vomEncoderEncode(b, 1)
}
}
func BenchmarkVomEncoder1000Customer(b *testing.B) {
for i := 0; i != b.N; i++ {
vomEncoderEncode(b, 1000)
}
}
// vom.Encoder.Encode RawValue benchmarking
func vomEncoderEncodeRawValue(t testing.TB, n int, rv *vom.RawValue) {
var buf bytes.Buffer
encoder := vom.NewVersionedEncoder(vom.Version81, &buf)
for j := 0; j != n; j++ {
err := encoder.Encode(rv)
if err != nil {
t.Fatalf("encoder.Encode failed: %v", err)
}
}
}
func makeCustomerRawValue(tb testing.TB) *vom.RawValue {
bytes, err := vom.Encode(customer)
if err != nil {
tb.Fatalf("vom.Encode failed: %v", err)
}
var rv vom.RawValue
if err := vom.Decode(bytes, &rv); err != nil {
tb.Fatalf("vom.Decode failed: %v", err)
}
return &rv
}
func BenchmarkVomEncoder1000RawValue(b *testing.B) {
rv := makeCustomerRawValue(b)
b.ResetTimer()
for i := 0; i != b.N; i++ {
vomEncoderEncodeRawValue(b, 1000, rv)
}
}
// ------------------------------------
// vom.Decoder.Decode benchmarking
func vomDecoderDecode(t testing.TB, n int, buf []byte) {
var c Customer
decoder := vom.NewDecoder(bytes.NewReader(buf))
for j := 0; j != n; j++ {
err := decoder.Decode(&c)
if err != nil {
t.Fatalf("decoder.Decode failed: %v", err)
}
}
}
func TestVomDecoder(t *testing.T) {
var buf bytes.Buffer
encoder := vom.NewEncoder(&buf)
for j := 0; j != 1000; j++ {
err := encoder.Encode(customer)
if err != nil {
t.Fatalf("encoder.Encode failed")
}
}
data := buf.Bytes()
fmt.Printf("Allocations per vom.Decoder.Decode (1 Customer) : %6.0f\n",
testing.AllocsPerRun(10, func() { vomDecoderDecode(t, 1, data) }))
fmt.Printf("Allocations per vom.Decoder.Decode (1000 Customers): %6.0f\n",
testing.AllocsPerRun(10, func() { vomDecoderDecode(t, 1000, data) }))
fmt.Printf("Allocations per vom.Decoder.Decode (1000 RawValues): %6.0f\n",
testing.AllocsPerRun(10, func() { vomDecoderDecodeRawValue(t, 1000, data) }))
}
func BenchmarkVomDecoder1Customer(b *testing.B) {
var buf bytes.Buffer
encoder := vom.NewEncoder(&buf)
err := encoder.Encode(customer)
if err != nil {
b.Fatalf("encoder.Encode failed")
}
data := buf.Bytes()
b.ResetTimer()
for i := 0; i != b.N; i++ {
vomDecoderDecode(b, 1, data)
}
}
func BenchmarkVomDecoder1000Customer(b *testing.B) {
var buf bytes.Buffer
encoder := vom.NewEncoder(&buf)
for j := 0; j != 1000; j++ {
err := encoder.Encode(customer)
if err != nil {
b.Fatalf("encoder.Encode failed")
}
}
data := buf.Bytes()
b.ResetTimer()
for i := 0; i != b.N; i++ {
vomDecoderDecode(b, 1000, data)
}
}
// vom.Decoder.Decode RawValue benchmarking
func vomDecoderDecodeRawValue(t testing.TB, n int, buf []byte) {
var rv vom.RawValue
decoder := vom.NewDecoder(bytes.NewReader(buf))
for j := 0; j != n; j++ {
err := decoder.Decode(&rv)
if err != nil {
t.Fatalf("decoder.Decode into raw value failed: %v", err)
}
}
}
func BenchmarkVomDecoder1000RawValue(b *testing.B) {
var buf bytes.Buffer
encoder := vom.NewVersionedEncoder(vom.Version81, &buf)
for j := 0; j != 1000; j++ {
err := encoder.Encode(customer)
if err != nil {
b.Fatalf("encoder.Encode failed")
}
}
data := buf.Bytes()
b.ResetTimer()
for i := 0; i != b.N; i++ {
vomDecoderDecodeRawValue(b, 1000, data)
}
}
// ------------------------------------
// gob.Encoder.Encode benchmarking
func gobEncoderEncode(t testing.TB, n int) {
var buf bytes.Buffer
encoder := gob.NewEncoder(&buf)
for j := 0; j != n; j++ {
err := encoder.Encode(customer)
if err != nil {
t.Fatalf("encoder.Encode failed: %v", err)
}
}
}
func TestGobEncoder(t *testing.T) {
fmt.Printf("Allocations per gob.Encoder.Encode (1 Customer) : %6.0f\n",
testing.AllocsPerRun(10, func() { gobEncoderEncode(t, 1) }))
fmt.Printf("Allocations per gob.Encoder.Encode (1000 Customers): %6.0f\n",
testing.AllocsPerRun(10, func() { gobEncoderEncode(t, 1000) }))
}
func BenchmarkGobEncoder1Customer(b *testing.B) {
for i := 0; i != b.N; i++ {
gobEncoderEncode(b, 1)
}
}
func BenchmarkGobEncoder1000Customer(b *testing.B) {
for i := 0; i != b.N; i++ {
gobEncoderEncode(b, 1000)
}
}
// ------------------------------------
// gob.Decoder.Decode benchmarking
func init() {
gob.Register(AgencyReportEquifaxReport{})
}
func gobDecoderDecode(t testing.TB, n int, buf []byte) {
var c Customer
decoder := gob.NewDecoder(bytes.NewReader(buf))
for j := 0; j != n; j++ {
err := decoder.Decode(&c)
if err != nil {
t.Fatalf("decoder.Decode failed: %v", err)
}
}
}
func TestGobDecoder(t *testing.T) {
var buf bytes.Buffer
encoder := gob.NewEncoder(&buf)
for j := 0; j != 1000; j++ {
err := encoder.Encode(customer)
if err != nil {
t.Fatalf("encoder.Encode failed")
}
}
data := buf.Bytes()
fmt.Printf("Allocations per gob.Decoder.Decode (1 Customer) : %6.0f\n",
testing.AllocsPerRun(10, func() { gobDecoderDecode(t, 1, data) }))
fmt.Printf("Allocations per gob.Decoder.Decode (1000 Customers): %6.0f\n",
testing.AllocsPerRun(10, func() { gobDecoderDecode(t, 1000, data) }))
}
func BenchmarkGobDecoder1Customer(b *testing.B) {
var buf bytes.Buffer
encoder := gob.NewEncoder(&buf)
err := encoder.Encode(customer)
if err != nil {
b.Fatalf("encoder.Encode failed")
}
data := buf.Bytes()
b.ResetTimer()
for i := 0; i != b.N; i++ {
gobDecoderDecode(b, 1, data)
}
}
func BenchmarkGobDecoder1000Customer(b *testing.B) {
var buf bytes.Buffer
encoder := gob.NewEncoder(&buf)
for j := 0; j != 1000; j++ {
err := encoder.Encode(customer)
if err != nil {
b.Fatalf("encoder.Encode failed")
}
}
data := buf.Bytes()
b.ResetTimer()
for i := 0; i != b.N; i++ {
gobDecoderDecode(b, 1000, data)
}
}