go-capnp icon indicating copy to clipboard operation
go-capnp copied to clipboard

Do you have the benchmark comparison to protobuf golang?

Open titanxxh opened this issue 5 years ago • 2 comments

The struct used is the example from Cap'n official site I wrote a same struct in protobuf. my test code is here: For protobuf and Cap'n, I do marshal and unmarshal for each run.

func capPerson() (*capnp.Message, debug.Person) {
	arena := capnp.SingleSegment(nil)
	msg, seg, _ := capnp.NewMessage(arena)
	p, _ := debug.NewRootPerson(seg)
	_ = p.SetName("xxh")
	date, _ := p.NewBirthdate()
	date.SetYear(1991)
	date.SetMonth(10)
	date.SetDay(26)
	_ = p.SetEmail("[email protected]")
	phones, _ := p.NewPhones(3)
	phones.At(0).SetNumber("8888888888")
	phones.At(0).SetType(debug.Person_PhoneNumber_Type_mobile)
	phones.At(1).SetNumber("wedonotsow")
	phones.At(1).SetType(debug.Person_PhoneNumber_Type_work)
	phones.At(2).SetNumber("helloworld")
	phones.At(2).SetType(debug.Person_PhoneNumber_Type_home)
	return msg, p
}

func protoPerson() *pd.Person {
	return &pd.Person{
		Name:                 "xxh",
		BirthDate:            &pd.Date{
			Year:                 1991,
			Month:                10,
			Day:                  26,
		},
		Email:                "[email protected]",
		Phones:               []*pd.Person_PhoneNumber{
			{Number:"8888888888", Typ: pd.Person_PhoneNumber_mobile},
			{Number:"wedonotsow", Typ: pd.Person_PhoneNumber_work},
			{Number:"helloworld", Typ: pd.Person_PhoneNumber_home},
		},
	}
}

func BenchmarkProto(b *testing.B) {
	obj := protoPerson()
	b.ResetTimer()
	b.ReportAllocs()
	for n:=0; n<b.N;n++ {
		buf, _ := proto.Marshal(obj)
		dox := pd.Person{}
		_ = proto.Unmarshal(buf, &dox)
	}
}

func BenchmarkCapn(b *testing.B) {
	msg, _ := capPerson()
	b.ResetTimer()
	b.ReportAllocs()
	for n:=0; n<b.N;n++ {
		buf, _ := msg.Marshal()
		msg2, _ := capnp.NewDecoder(bytes.NewBuffer(buf)).Decode()
		_, _ = debug.ReadRootPerson(msg2)
	}
}

BenchmarkProto-12 1000000 1098 ns/op 552 B/op 14 allocs/op BenchmarkCapn-12 2983165 399 ns/op 420 B/op 5 allocs/op

I am a newcomer to go-capnproto, so my code may get something wrong. If I want to achieve higher encode/decode speed, how can I change my bench code?

titanxxh avatar Dec 19 '19 04:12 titanxxh

This is a microbenchmark and isn't going to be necessarily representative of real-world performance. Given the setup, this seems pretty reasonable and mostly seems like you're exercising the speed of the allocator/GC. Profiling can confirm this hypothesis.

That said, if you're really looking to game the benchmark, you can pass in a preallocated buffer to SingleSegment to reduce allocations.

zombiezen avatar Dec 20 '19 16:12 zombiezen

@zombiezen Out of sheer interest, does go-canproto's design support reusing buffers or segments e.g. with sync.Pool? How would that work?

lthibault avatar Apr 07 '20 19:04 lthibault