Skip to content

(gogoproto.stdtime) = true causes low marshal performance #656

@TennyZhuang

Description

@TennyZhuang

gogo/protobuf/types.Timestamp is generated by protoc-gen-gogo and imports gogo/protobuf/proto.

To avoid cycling import, gogo/protobuf implement a fake timestamp .

type timestamp struct {
Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
}
func (m *timestamp) Reset() { *m = timestamp{} }
func (*timestamp) ProtoMessage() {}
func (*timestamp) String() string { return "timestamp<string>" }

And it does not implement newMarshaler or Marshaler interface, which will cause the Marshal use the slowest path.

var info InternalMessageInfo
siz := info.Size(pb)
b := make([]byte, 0, siz)
return info.Marshal(b, pb, false)

Then the global marshal info lock will be performance bottleneck.

func getMarshalInfo(t reflect.Type) *marshalInfo {
marshalInfoLock.Lock()
u, ok := marshalInfoMap[t]
if !ok {
u = &marshalInfo{typ: t}
marshalInfoMap[t] = u
}
marshalInfoLock.Unlock()
return u
}

image

A simple workaround fix is #655

A better solution is use a real Timestamp instead of a fake timestamp.

To avoid cycling import, we can import golang/protobuf and use Timestamp generated by golang protobuf.

import ptimestamp "github.com/golang/protobuf/ptypes/timestamp"

type timestamp = ptimestamp.Timestamp

Then the performance will be highly improved.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions