frostfs-api-go/object/lock.go
Evgenii Stratonikov 5e1c6a908f [#111] protogen: Emit slice of messages without a pointer
```
goos: linux
goarch: amd64
pkg: git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs
cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
                                              │      old      │                 new                  │
                                              │    sec/op     │    sec/op     vs base                │
ObjectIDSlice/0_elements/to_grpc_message-8       3.193n ±  2%   3.242n ±  0%   +1.50% (p=0.034 n=10)
ObjectIDSlice/0_elements/from_grpc_message-8     3.197n ±  2%   3.343n ±  1%   +4.57% (p=0.000 n=10)
ObjectIDSlice/0_elements/marshal-8               5.666n ±  3%   5.642n ±  0%   -0.42% (p=0.000 n=10)
ObjectIDSlice/1_elements/to_grpc_message-8       53.10n ±  6%   29.78n ± 12%  -43.92% (p=0.000 n=10)
ObjectIDSlice/1_elements/from_grpc_message-8     28.99n ±  5%   29.77n ±  7%        ~ (p=0.165 n=10)
ObjectIDSlice/1_elements/marshal-8               49.08n ±  7%   50.72n ±  6%        ~ (p=0.218 n=10)
ObjectIDSlice/50_elements/to_grpc_message-8     1652.5n ±  7%   277.2n ±  1%  -83.22% (p=0.000 n=10)
ObjectIDSlice/50_elements/from_grpc_message-8    261.2n ± 11%   226.7n ± 15%  -13.19% (p=0.003 n=10)
ObjectIDSlice/50_elements/marshal-8              1.512µ ±  6%   1.514µ ±  6%        ~ (p=0.955 n=10)
geomean                                          52.15n         39.99n        -23.31%

                                              │      old       │                  new                   │
                                              │      B/op      │     B/op      vs base                  │
ObjectIDSlice/0_elements/to_grpc_message-8        0.000 ± 0%       0.000 ± 0%        ~ (p=1.000 n=10) ¹
ObjectIDSlice/0_elements/from_grpc_message-8      0.000 ± 0%       0.000 ± 0%        ~ (p=1.000 n=10) ¹
ObjectIDSlice/0_elements/marshal-8                0.000 ± 0%       0.000 ± 0%        ~ (p=1.000 n=10) ¹
ObjectIDSlice/1_elements/to_grpc_message-8        32.00 ± 0%       24.00 ± 0%  -25.00% (p=0.000 n=10)
ObjectIDSlice/1_elements/from_grpc_message-8      24.00 ± 0%       24.00 ± 0%        ~ (p=1.000 n=10) ¹
ObjectIDSlice/1_elements/marshal-8                48.00 ± 0%       48.00 ± 0%        ~ (p=1.000 n=10) ¹
ObjectIDSlice/50_elements/to_grpc_message-8     1.578Ki ± 0%     1.250Ki ± 0%  -20.79% (p=0.000 n=10)
ObjectIDSlice/50_elements/from_grpc_message-8   1.250Ki ± 0%     1.250Ki ± 0%        ~ (p=1.000 n=10) ¹
ObjectIDSlice/50_elements/marshal-8             2.000Ki ± 0%     2.000Ki ± 0%        ~ (p=1.000 n=10) ¹
geomean                                                      ²                  -5.62%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                              │      old      │                 new                  │
                                              │   allocs/op   │ allocs/op   vs base                  │
ObjectIDSlice/0_elements/to_grpc_message-8       0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
ObjectIDSlice/0_elements/from_grpc_message-8     0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
ObjectIDSlice/0_elements/marshal-8               0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
ObjectIDSlice/1_elements/to_grpc_message-8       2.000 ± 0%     1.000 ± 0%  -50.00% (p=0.000 n=10)
ObjectIDSlice/1_elements/from_grpc_message-8     1.000 ± 0%     1.000 ± 0%        ~ (p=1.000 n=10) ¹
ObjectIDSlice/1_elements/marshal-8               1.000 ± 0%     1.000 ± 0%        ~ (p=1.000 n=10) ¹
ObjectIDSlice/50_elements/to_grpc_message-8     51.000 ± 0%     1.000 ± 0%  -98.04% (p=0.000 n=10)
ObjectIDSlice/50_elements/from_grpc_message-8    1.000 ± 0%     1.000 ± 0%        ~ (p=1.000 n=10) ¹
ObjectIDSlice/50_elements/marshal-8              1.000 ± 0%     1.000 ± 0%        ~ (p=1.000 n=10) ¹
geomean                                                     ²               -40.18%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-08-28 11:53:08 +03:00

160 lines
3.3 KiB
Go

package object
import (
"errors"
"fmt"
lock "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/lock/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto"
)
// Lock represents object Lock message from NeoFS API V2 protocol.
type Lock struct {
members []refs.ObjectID
}
// NumberOfMembers returns length of lock list.
func (x *Lock) NumberOfMembers() int {
if x != nil {
return len(x.members)
}
return 0
}
// IterateMembers passes members of the lock list to f.
func (x *Lock) IterateMembers(f func(refs.ObjectID)) {
if x != nil {
for i := range x.members {
f(x.members[i])
}
}
}
// SetMembers sets list of locked members.
// Arg must not be mutated for the duration of the Lock.
func (x *Lock) SetMembers(ids []refs.ObjectID) {
x.members = ids
}
const (
_ = iota
fNumLockMembers
)
// StableMarshal encodes the Lock into Protocol Buffers binary format
// with direct field order.
func (x *Lock) StableMarshal(buf []byte) []byte {
if x == nil || len(x.members) == 0 {
return []byte{}
}
if buf == nil {
buf = make([]byte, x.StableSize())
}
var offset int
for i := range x.members {
offset += proto.NestedStructureMarshal(fNumLockMembers, buf[offset:], &x.members[i])
}
return buf
}
// StableSize size of the buffer required to write the Lock in Protocol Buffers
// binary format.
func (x *Lock) StableSize() (sz int) {
if x != nil {
for i := range x.members {
sz += proto.NestedStructureSize(fNumLockMembers, &x.members[i])
}
}
return
}
// Unmarshal decodes the Lock from its Protocol Buffers binary format.
func (x *Lock) Unmarshal(data []byte) error {
return message.Unmarshal(x, data, new(lock.Lock))
}
func (x *Lock) ToGRPCMessage() grpc.Message {
var m *lock.Lock
if x != nil {
m = new(lock.Lock)
var members []refsGRPC.ObjectID
if x.members != nil {
members = make([]refsGRPC.ObjectID, len(x.members))
for i := range x.members {
members[i] = *x.members[i].ToGRPCMessage().(*refsGRPC.ObjectID)
}
}
m.SetMembers(members)
}
return m
}
func (x *Lock) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*lock.Lock)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
members := v.GetMembers()
if members == nil {
x.members = nil
} else {
x.members = make([]refs.ObjectID, len(members))
var err error
for i := range x.members {
err = x.members[i].FromGRPCMessage(&members[i])
if err != nil {
return err
}
}
}
return nil
}
// WriteLock writes Lock to the Object as a payload content.
// The object must not be nil.
func WriteLock(obj *Object, lock Lock) {
hdr := obj.GetHeader()
if hdr == nil {
hdr = new(Header)
obj.SetHeader(hdr)
}
hdr.SetObjectType(TypeLock)
payload := lock.StableMarshal(nil)
obj.SetPayload(payload)
}
// ReadLock reads Lock from the Object payload content.
func ReadLock(lock *Lock, obj Object) error {
payload := obj.GetPayload()
if len(payload) == 0 {
return errors.New("empty payload")
}
err := lock.Unmarshal(payload)
if err != nil {
return fmt.Errorf("decode lock content from payload: %w", err)
}
return nil
}