Skip to content

Commit

Permalink
node/object: Optimize memory allocs for objects with known payload size
Browse files Browse the repository at this point in the history
Previously, storage nodes slicing user data stream into NeoFS objects
did not process payload size when it was specified in the request. Since
any NeoFS cluster has a system parameter that limits the maximum size
of a physically stored object, the node allocated a buffer equal to its
value.For "large" objects this was quite acceptable and optimal. However,
the smaller the amount of data that was sliced, the more redundant
memory was allocated. According to the protocol, the size of the stored
data may be unknown, so we cannot always rely on knowing the size of
the streaming data. However, in the case when this parameter is
specified in the request, nothing prevents the node from using its
value to allocate a small enough buffer. In particular, this will
significantly reduce memory consumption during mass streaming of “small”
data.

The updated version of the NeoFS SDK library supports processing a
previously known amount of data in-box. All the application needs is to
set `SetPayloadSize` slicing option.

It's hard to imagine simpler approach. But there were some nuances.
According to NeoFS API protocol, a zero header field is considered an
explicit setting of the object without a payload, while an unspecified
size is passed as all bits set in the field. However, NeoFS nodes for a
long time regarded any value, including zero, as a dynamic size. Since
zero also means a “forgotten” field, we cannot suddenly begin to
perceive it as an object without a payload. Therefore, for update
security, only non-zero values other than the maximum possible are
processed as the size set by the user.

In total, the applied optimization will not cover all cases, but for
some of them it significantly increases performance and efficiency.

Refs #2686.

Signed-off-by: Leonard Lyubich <[email protected]>
  • Loading branch information
cthulhu-rider committed Jan 30, 2024
1 parent 08a531a commit 153d56a
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Changelog for NeoFS Node
- IR does not create new notary requests for the SN's bootstraps but signs the received ones instead (#2717)
- IR can handle third-party notary requests without reliance on receiving the original one (#2715)
- SN validates container session token's issuer to be container's owner (#2466)
- Storage node now consumes much less memory when slicing small data of a fixed size (#2719)

### Removed
- Deprecated `neofs-adm [...] inspect` commands (#2603)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ require (
github.com/nspcc-dev/neo-go v0.104.0
github.com/nspcc-dev/neofs-api-go/v2 v2.14.0
github.com/nspcc-dev/neofs-contract v0.19.1
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20231121125354-d72d76ccb0ba
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240130073207-03ed6db7e1cd
github.com/nspcc-dev/tzhash v1.7.1
github.com/olekukonko/tablewriter v0.0.5
github.com/panjf2000/ants/v2 v2.8.2
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ github.com/nspcc-dev/neofs-contract v0.19.1 h1:U1Uh+MlzfkalO0kRJ2pADZyHrmAOroC6K
github.com/nspcc-dev/neofs-contract v0.19.1/go.mod h1:ZOGouuwuHpgvYkx/LCGufGncIzEUhYEO18LL4cWEbyw=
github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4=
github.com/nspcc-dev/neofs-crypto v0.4.0/go.mod h1:6XJ8kbXgOfevbI2WMruOtI+qUJXNwSGM/E9eClXxPHs=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20231121125354-d72d76ccb0ba h1:dQDBBqmT2rlJGgkeeF3UurB3VgG7buMHDHcz5UQ3bro=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20231121125354-d72d76ccb0ba/go.mod h1:2PKUuH7kQaAmQ/USBgmiD/k08ssnSvayor6JAFhrC1c=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240130073207-03ed6db7e1cd h1:kRIn6i7BTa55ae4cH+UcqRfH//XC20mSC4E9WcWxkmM=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240130073207-03ed6db7e1cd/go.mod h1:2PKUuH7kQaAmQ/USBgmiD/k08ssnSvayor6JAFhrC1c=
github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE=
github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso=
github.com/nspcc-dev/tzhash v1.7.1 h1:6zmexLqdTF/ssbUAh7XJS7RxgKWaw28kdNpE/4UFdEU=
Expand Down
8 changes: 8 additions & 0 deletions pkg/services/object/put/slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package putsvc
import (
"context"
"fmt"
"math"

"github.com/nspcc-dev/neofs-node/pkg/services/object/internal"
"github.com/nspcc-dev/neofs-sdk-go/client"
Expand Down Expand Up @@ -60,6 +61,13 @@ func (x *slicingTarget) WriteHeader(hdr *object.Object) error {
opts.CalculateHomomorphicChecksum()
}

if payloadSize := hdr.PayloadSize(); payloadSize != 0 && payloadSize != math.MaxUint64 {
// https://github.com/nspcc-dev/neofs-api/blob/d95228c40283cf6e188073a87a802af7e5dc0a7d/object/types.proto#L93-L95
// zero may be explicitly set and be true, but node previously considered zero
// value as unknown payload, so we keep this behavior for now
opts.SetPayloadSize(payloadSize)
}

var err error
x.payloadWriter, err = slicer.InitPut(x.ctx, &readyObjectWriter{
nextTarget: x.nextTarget,
Expand Down

0 comments on commit 153d56a

Please sign in to comment.