mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-04-16 08:42:29 +00:00
proto: replace CachedSize fast-path method with UseCachedSize option
Using an option instead of a separate method has several useful properties: It makes it explicit whether the fast-path AppendMarshal is expected to use cached sizes or not. It properly plumbs the decision to use cached sizes through the call stack. Consider the case where message A includes B includes C: If A and C support cached sizes but B does not, we would like to use the size cache in all messages which support it. Placing this decision in the options allows this to work properly with no additional effort. Placing this option in MarshalOptions permits users to request use of existing cached sizes. This is a two-edged sword: There are places where this ability can permit substantial efficiencies, but this is also an exceedingly sharp-edged API. I believe that on balance the benefits outweigh the risks, especially since the prerequisites for using cached sizes are intuitively obvious. (You must have called Size, and you must not have changed the message.) This CL adds a Size method to MarshalOptions, rather than adding a SizeOptions type. Future additions to MarshalOptions may affect the size of the encoded output (e.g., an option to skip encoding unknown fields) and using the same options for both Marshal and Size makes it easier to use a consistent configuration for each. Change-Id: I6adbb55b717dd03d39f067e1d0b7381945000976 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171119 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
parent
3016b73382
commit
03e748680c
@ -47,6 +47,26 @@ type MarshalOptions struct {
|
|||||||
// detail and subject to change.
|
// detail and subject to change.
|
||||||
Deterministic bool
|
Deterministic bool
|
||||||
|
|
||||||
|
// UseCachedSize indicates that the result of a previous Size call
|
||||||
|
// may be reused.
|
||||||
|
//
|
||||||
|
// Setting this option asserts that:
|
||||||
|
//
|
||||||
|
// 1. Size has previously been called on this message with identical
|
||||||
|
// options (except for UseCachedSize itself).
|
||||||
|
//
|
||||||
|
// 2. The message and all its submessages have not changed in any
|
||||||
|
// way since the Size call.
|
||||||
|
//
|
||||||
|
// If either of these invariants is broken, the results are undefined
|
||||||
|
// but may include panics or invalid output.
|
||||||
|
//
|
||||||
|
// Implementations MAY take this option into account to provide
|
||||||
|
// better performance, but there is no guarantee that they will do so.
|
||||||
|
// There is absolutely no guarantee that Size followed by Marshal with
|
||||||
|
// UseCachedSize set will perform equivalently to Marshal alone.
|
||||||
|
UseCachedSize bool
|
||||||
|
|
||||||
pragma.NoUnkeyedLiterals
|
pragma.NoUnkeyedLiterals
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +113,7 @@ func (o MarshalOptions) marshalMessageFast(b []byte, m Message) ([]byte, error)
|
|||||||
copy(x, b)
|
copy(x, b)
|
||||||
b = x
|
b = x
|
||||||
}
|
}
|
||||||
|
o.UseCachedSize = true
|
||||||
}
|
}
|
||||||
return methods.MarshalAppend(b, m, protoiface.MarshalOptions(o))
|
return methods.MarshalAppend(b, m, protoiface.MarshalOptions(o))
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,11 @@ import (
|
|||||||
|
|
||||||
// Size returns the size in bytes of the wire-format encoding of m.
|
// Size returns the size in bytes of the wire-format encoding of m.
|
||||||
func Size(m Message) int {
|
func Size(m Message) int {
|
||||||
|
return MarshalOptions{}.Size(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns the size in bytes of the wire-format encoding of m.
|
||||||
|
func (o MarshalOptions) Size(m Message) int {
|
||||||
if size, err := sizeMessageFast(m); err == nil {
|
if size, err := sizeMessageFast(m); err == nil {
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,6 @@ type Methods struct {
|
|||||||
// Size returns the size in bytes of the wire-format encoding of m.
|
// Size returns the size in bytes of the wire-format encoding of m.
|
||||||
Size func(m protoreflect.ProtoMessage) int
|
Size func(m protoreflect.ProtoMessage) int
|
||||||
|
|
||||||
// CachedSize returns the result of the last call to Size.
|
|
||||||
// It must not be called if the message has been changed since the last call to Size.
|
|
||||||
CachedSize func(m protoreflect.ProtoMessage) int
|
|
||||||
|
|
||||||
// Unmarshal parses the wire-format message in b and places the result in m.
|
// Unmarshal parses the wire-format message in b and places the result in m.
|
||||||
// It does not reset m or perform required field checks.
|
// It does not reset m or perform required field checks.
|
||||||
Unmarshal func(b []byte, m protoreflect.ProtoMessage, opts UnmarshalOptions) error
|
Unmarshal func(b []byte, m protoreflect.ProtoMessage, opts UnmarshalOptions) error
|
||||||
@ -55,6 +51,7 @@ const (
|
|||||||
type MarshalOptions struct {
|
type MarshalOptions struct {
|
||||||
AllowPartial bool
|
AllowPartial bool
|
||||||
Deterministic bool
|
Deterministic bool
|
||||||
|
UseCachedSize bool
|
||||||
|
|
||||||
pragma.NoUnkeyedLiterals
|
pragma.NoUnkeyedLiterals
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user