Skip to content

Commit 8119ed2

Browse files
wip one-alloc unmarshal
1 parent eca656e commit 8119ed2

File tree

3 files changed

+117
-23
lines changed

3 files changed

+117
-23
lines changed

features/zeropb/zeropb.go

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ const (
1919
runtimePackage = protogen.GoImportPath("github.com/cosmos/cosmos-proto/runtime/zeropb")
2020
)
2121

22+
const unsafeOptimizations = true
23+
2224
func init() {
2325
generator.RegisterFeature("zeropb", func(gen *generator.GeneratedFile, _ *protogen.Plugin) generator.FeatureGenerator {
2426
return zeropbFeature{
@@ -179,8 +181,6 @@ func (g zeropbFeature) generateMarshalPrimitive(f *protogen.Field, name, offset
179181
}
180182
}
181183

182-
const unsafeOptimizations = true
183-
184184
func (g zeropbFeature) generateUnmarshal(m *protogen.Message) {
185185
g.gen.P("func (x *", m.GoIdent, ") UnmarshalZeroPB(buf []byte) (err error) {")
186186
g.gen.P(" defer func() {")
@@ -190,21 +190,71 @@ func (g zeropbFeature) generateUnmarshal(m *protogen.Message) {
190190
g.gen.P(" }()")
191191
g.gen.P(" var mem []byte")
192192
if unsafeOptimizations {
193-
g.gen.P("mem = make([]byte, 251)")
193+
g.gen.P("memSize := _", m.GoIdent, "UnmarshalZeroPBSize(buf, 0)")
194+
g.gen.P("mem = make([]byte, memSize)")
194195
}
195196
g.gen.P(" x.unmarshalZeroPB(buf, 0, ", runtimePackage.Ident("NewBuffer"), "(mem))")
196197
g.gen.P(" return nil")
197198
g.gen.P("}")
198199
g.gen.P()
199-
g.gen.P("func (x *", m.GoIdent, ") unmarshalZeroPB(buf []byte, n uint16, mem *", runtimePackage.Ident("Buffer"), ") {")
200+
g.gen.P("func _", m.GoIdent, "UnmarshalZeroPBSize(buf []byte, n uint16) (size uint16) {")
200201
offset := 0
202+
for _, f := range m.Fields {
203+
g.generateUnmarshalFieldSize(f, m.GoIdent, offset)
204+
offset += fieldSize(f)
205+
}
206+
g.gen.P(" return")
207+
g.gen.P("}")
208+
g.gen.P("func (x *", m.GoIdent, ") unmarshalZeroPB(buf []byte, n uint16, mem *", runtimePackage.Ident("Buffer"), ") {")
209+
offset = 0
201210
for _, f := range m.Fields {
202211
g.generateUnmarshalField(f, offset)
203212
offset += fieldSize(f)
204213
}
205214
g.gen.P("}")
206215
}
207216

217+
func (g zeropbFeature) generateUnmarshalFieldSize(f *protogen.Field, typ protogen.GoIdent, offset int) {
218+
d := f.Desc
219+
switch {
220+
case d.IsList():
221+
g.gen.P("n_", d.Index(), ", len_", d.Index(), " := ", runtimePackage.Ident("ReadSlice"), "(buf, n+", offset, ")")
222+
g.gen.P("_ = n_", d.Index())
223+
g.gen.P("size += len_", d.Index(), "*uint16(", unsafePackage.Ident("Sizeof"), "((", typ, "{}).", f.GoName, "[0]))")
224+
g.gen.P("for i := uint16(0); i < len_", d.Index(), "; i++ {")
225+
// Skip segment header.
226+
g.generateUnmarshalPrimitiveSize(f, fmt.Sprintf("n_%d+%d+uint16(i)*%d", d.Index(), segmentHeaderSize, fieldElemSize(f)))
227+
g.gen.P("}")
228+
case d.IsMap():
229+
g.gen.P("n_", d.Index(), ", len_", d.Index(), " := ", runtimePackage.Ident("ReadSlice"), "(buf, n+", offset, ")")
230+
g.gen.P("{")
231+
g.gen.P(" n := n_", d.Index(), "; _ = n")
232+
g.gen.P(" for i := uint16(0); i < len_", d.Index(), "; i++ {")
233+
g.generateUnmarshalPrimitiveSize(f.Message.Fields[0], "n")
234+
g.gen.P(" n += ", fieldSize(f.Message.Fields[0]))
235+
g.generateUnmarshalPrimitiveSize(f.Message.Fields[1], "n")
236+
g.gen.P(" n += ", fieldSize(f.Message.Fields[1]))
237+
g.gen.P(" }")
238+
g.gen.P("}")
239+
case d.ContainingOneof() != nil:
240+
g.gen.P("// TODO: field ", f.GoName)
241+
default:
242+
g.generateUnmarshalPrimitiveSize(f, fmt.Sprintf("n+%d", offset))
243+
}
244+
}
245+
246+
func (g zeropbFeature) generateUnmarshalPrimitiveSize(f *protogen.Field, offset string) {
247+
switch d := f.Desc; d.Kind() {
248+
case protoreflect.StringKind, protoreflect.BytesKind:
249+
g.gen.P("_, len_", d.Index(), " := ", runtimePackage.Ident("ReadSlice"), "(buf, ", offset, ")")
250+
g.gen.P("size += len_", d.Index(), "*uint16(", unsafePackage.Ident("Sizeof"), "(byte(0)))")
251+
case protoreflect.MessageKind:
252+
g.gen.P("size += uint16(", unsafePackage.Ident("Sizeof"), "(", f.Message.GoIdent, "{}))")
253+
g.gen.P("size += _", f.Message.GoIdent, "UnmarshalZeroPBSize(buf, ", offset, ")")
254+
default:
255+
}
256+
}
257+
208258
func (g zeropbFeature) generateUnmarshalField(f *protogen.Field, offset int) {
209259
d := f.Desc
210260
switch {
@@ -217,11 +267,8 @@ func (g zeropbFeature) generateUnmarshalField(f *protogen.Field, offset int) {
217267
} else {
218268
g.gen.P("x.", f.GoName, " = make([]", typ, ", len_", d.Index(), ")")
219269
}
220-
g.gen.P("{")
221-
g.gen.P(" for i := range x.", f.GoName, "{")
222-
// Skip segment header.
223-
g.generateUnmarshalPrimitive(f, "x."+f.GoName+"[i]", fmt.Sprintf("n_%d+4+uint16(i)*%d", d.Index(), fieldElemSize(f)))
224-
g.gen.P(" }")
270+
g.gen.P("for i := range x.", f.GoName, "{")
271+
g.generateUnmarshalPrimitive(f, "x."+f.GoName+"[i]", fmt.Sprintf("n_%d+%d+uint16(i)*%d", d.Index(), segmentHeaderSize, fieldElemSize(f)))
225272
g.gen.P("}")
226273
case d.IsMap():
227274
g.gen.P("n_", d.Index(), ", len_", d.Index(), " := ", runtimePackage.Ident("ReadSlice"), "(buf, n+", offset, ")")
@@ -280,7 +327,7 @@ func (g zeropbFeature) generateUnmarshalPrimitive(f *protogen.Field, name, offse
280327
if d.Kind() == protoreflect.BytesKind {
281328
g.gen.P(name, " = mem_", d.Index(), ".Buf")
282329
} else {
283-
g.gen.P(name, " = ", unsafePackage.Ident("String"), "(unsafe.SliceData(mem_", d.Index(), ".Buf), len(mem_", d.Index(), ".Buf))")
330+
g.gen.P(name, " = ", unsafePackage.Ident("String"), "(", unsafePackage.Ident("SliceData"), "(mem_", d.Index(), ".Buf), len(mem_", d.Index(), ".Buf))")
284331
}
285332
} else {
286333
if d.Kind() == protoreflect.BytesKind {

testpb/1.pulsar.go

Lines changed: 55 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

testpb/2.pulsar.go

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)