From 98f56d1bd543eca52eff2c76e7c5364a939c91fd Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Tue, 21 Apr 2020 10:46:11 -0700 Subject: [PATCH] internal/impl: inline coderInfoFields for better cache locality Microbenchmarks are inconclusive/noisy, but shows a small but noticeable improvement on internal benchmarks. Change-Id: Ic46c6aac8a42c4dc749c4f3583d8c8c95e9548b7 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/229277 Reviewed-by: Joe Tsai --- internal/impl/codec_message.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/internal/impl/codec_message.go b/internal/impl/codec_message.go index 370ec65a..03b096e5 100644 --- a/internal/impl/codec_message.go +++ b/internal/impl/codec_message.go @@ -31,6 +31,11 @@ type coderMessageInfo struct { needsInitCheck bool isMessageSet bool numRequiredFields uint8 + + // Include space for a number of coderFieldInfos to improve cache locality. + // The number of entries is chosen through a combination of guesswork and + // empirical testing. + coderFieldBuf [32]coderFieldInfo } type coderFieldInfo struct { @@ -53,6 +58,7 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) { mi.coderFields = make(map[protowire.Number]*coderFieldInfo) fields := mi.Desc.Fields() + preallocFields := mi.coderFieldBuf[:] for i := 0; i < fields.Len(); i++ { fd := fields.Get(i) @@ -80,7 +86,14 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) { fieldOffset = offsetOf(fs, mi.Exporter) childMessage, funcs = fieldCoder(fd, ft) } - cf := &coderFieldInfo{ + var cf *coderFieldInfo + if len(preallocFields) > 0 { + cf = &preallocFields[0] + preallocFields = preallocFields[1:] + } else { + cf = new(coderFieldInfo) + } + *cf = coderFieldInfo{ num: fd.Number(), offset: fieldOffset, wiretag: wiretag,