[#58] object: Allow to set marshal data
Now it is possible set marshaled data to reduce memory allocations. Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com> Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
parent
ff2290fa93
commit
bc214f6abe
5 changed files with 94 additions and 4 deletions
|
@ -322,6 +322,14 @@ func (o *Object) StableMarshal(buf []byte) []byte {
|
||||||
return []byte{}
|
return []byte{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if o.marshalData != nil {
|
||||||
|
if buf == nil {
|
||||||
|
return o.marshalData
|
||||||
|
}
|
||||||
|
copy(buf, o.marshalData)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
if buf == nil {
|
if buf == nil {
|
||||||
buf = make([]byte, o.StableSize())
|
buf = make([]byte, o.StableSize())
|
||||||
}
|
}
|
||||||
|
@ -336,6 +344,20 @@ func (o *Object) StableMarshal(buf []byte) []byte {
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetMarshalData sets marshal data to reduce memory allocations.
|
||||||
|
//
|
||||||
|
// It is unsafe to modify object data after setting marshal data.
|
||||||
|
func (o *Object) SetMarshalData(data []byte) {
|
||||||
|
if o == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if data == nil {
|
||||||
|
o.marshalData = o.StableMarshal(nil)
|
||||||
|
} else {
|
||||||
|
o.marshalData = data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Object) StableSize() (size int) {
|
func (o *Object) StableSize() (size int) {
|
||||||
if o == nil {
|
if o == nil {
|
||||||
return 0
|
return 0
|
||||||
|
@ -1071,6 +1093,15 @@ func (r *PutSingleRequestBody) StableMarshal(buf []byte) []byte {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return []byte{}
|
return []byte{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if r.marshalData != nil {
|
||||||
|
if buf == nil {
|
||||||
|
return r.marshalData
|
||||||
|
}
|
||||||
|
copy(buf, r.marshalData)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
if buf == nil {
|
if buf == nil {
|
||||||
buf = make([]byte, r.StableSize())
|
buf = make([]byte, r.StableSize())
|
||||||
}
|
}
|
||||||
|
@ -1082,6 +1113,23 @@ func (r *PutSingleRequestBody) StableMarshal(buf []byte) []byte {
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetMarshalData sets marshal data to reduce memory allocations.
|
||||||
|
//
|
||||||
|
// It is unsafe to modify request data after setting marshal data.
|
||||||
|
func (r *PutSingleRequestBody) SetMarshalData(data []byte) {
|
||||||
|
if r == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if data == nil {
|
||||||
|
r.marshalData = r.StableMarshal(nil)
|
||||||
|
} else {
|
||||||
|
r.marshalData = data
|
||||||
|
}
|
||||||
|
|
||||||
|
proto.NestedStructureSetMarshalData(putSingleReqObjectField, r.marshalData, r.object)
|
||||||
|
}
|
||||||
|
|
||||||
func (r *PutSingleRequestBody) StableSize() int {
|
func (r *PutSingleRequestBody) StableSize() int {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return 0
|
return 0
|
||||||
|
|
|
@ -75,6 +75,9 @@ type Object struct {
|
||||||
header *Header
|
header *Header
|
||||||
|
|
||||||
payload []byte
|
payload []byte
|
||||||
|
|
||||||
|
// marshalData holds marshaled data, must not be marshaled by StableMarshal
|
||||||
|
marshalData []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type SplitInfo struct {
|
type SplitInfo struct {
|
||||||
|
@ -304,6 +307,9 @@ type GetRangeHashResponse struct {
|
||||||
type PutSingleRequestBody struct {
|
type PutSingleRequestBody struct {
|
||||||
object *Object
|
object *Object
|
||||||
copyNum []uint32
|
copyNum []uint32
|
||||||
|
|
||||||
|
// marshalData holds marshaled data, must not be marshaled by StableMarshal
|
||||||
|
marshalData []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type PutSingleRequest struct {
|
type PutSingleRequest struct {
|
||||||
|
|
|
@ -19,6 +19,11 @@ type (
|
||||||
StableMarshal([]byte) []byte
|
StableMarshal([]byte) []byte
|
||||||
StableSize() int
|
StableSize() int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setMarshalData interface {
|
||||||
|
SetMarshalData([]byte)
|
||||||
|
StableSize() int
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func BytesMarshal(field int, buf, v []byte) int {
|
func BytesMarshal(field int, buf, v []byte) int {
|
||||||
|
@ -263,6 +268,26 @@ func NestedStructureMarshal[T stableMarshaller](field int64, buf []byte, v T) in
|
||||||
return offset + n
|
return offset + n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NestedStructureSetMarshalData calculates offset for field in parentData
|
||||||
|
// and calls SetMarshalData for nested structure.
|
||||||
|
//
|
||||||
|
// Returns marshalled data length of nested structure.
|
||||||
|
func NestedStructureSetMarshalData(field int64, parentData []byte, v setMarshalData) int {
|
||||||
|
n := v.StableSize()
|
||||||
|
if n == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, binary.MaxVarintLen64)
|
||||||
|
prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType)
|
||||||
|
offset := binary.PutUvarint(buf, prefix)
|
||||||
|
offset += binary.PutUvarint(buf, uint64(n))
|
||||||
|
|
||||||
|
v.SetMarshalData(parentData[offset : offset+n])
|
||||||
|
|
||||||
|
return offset + n
|
||||||
|
}
|
||||||
|
|
||||||
func NestedStructureSize[T stableMarshaller](field int64, v T) (size int) {
|
func NestedStructureSize[T stableMarshaller](field int64, v T) (size int) {
|
||||||
n := v.StableSize()
|
n := v.StableSize()
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
|
|
|
@ -14,6 +14,13 @@ var buffersPool = sync.Pool{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tryGetNewBufferFromPool(size int) (*buffer, bool) {
|
||||||
|
if size > poolSliceMaxSize {
|
||||||
|
return &buffer{}, false
|
||||||
|
}
|
||||||
|
return newBufferFromPool(size), true
|
||||||
|
}
|
||||||
|
|
||||||
func newBufferFromPool(size int) *buffer {
|
func newBufferFromPool(size int) *buffer {
|
||||||
result := buffersPool.Get().(*buffer)
|
result := buffersPool.Get().(*buffer)
|
||||||
if cap(result.data) < size {
|
if cap(result.data) < size {
|
||||||
|
|
|
@ -35,8 +35,10 @@ func SignDataWithHandler(key *ecdsa.PrivateKey, src DataSource, handler KeySigna
|
||||||
opts[i](cfg)
|
opts[i](cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer := newBufferFromPool(src.SignedDataSize())
|
buffer, ok := tryGetNewBufferFromPool(src.SignedDataSize())
|
||||||
defer returnBufferToPool(buffer)
|
if ok {
|
||||||
|
defer returnBufferToPool(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
data, err := src.ReadSignedData(buffer.data)
|
data, err := src.ReadSignedData(buffer.data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -64,8 +66,10 @@ func VerifyDataWithSource(dataSrc DataSource, sigSrc KeySignatureSource, opts ..
|
||||||
opts[i](cfg)
|
opts[i](cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer := newBufferFromPool(dataSrc.SignedDataSize())
|
buffer, ok := tryGetNewBufferFromPool(dataSrc.SignedDataSize())
|
||||||
defer returnBufferToPool(buffer)
|
if ok {
|
||||||
|
defer returnBufferToPool(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
data, err := dataSrc.ReadSignedData(buffer.data)
|
data, err := dataSrc.ReadSignedData(buffer.data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue