go-capnp
go-capnp copied to clipboard
Do you have the benchmark comparison to protobuf golang?
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?
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 Out of sheer interest, does go-canproto's design support reusing buffers or segments e.g. with sync.Pool
? How would that work?