[#19] transformer: Do not allocate intermeate slice for hashers

```
name                 old time/op    new time/op    delta
Transformer/small-8    73.7µs ±15%    72.4µs ±16%    ~     (p=0.604 n=10+9)
Transformer/big-8       1.36s ± 4%     1.36s ± 8%    ~     (p=0.579 n=10+10)

name                 old alloc/op   new alloc/op   delta
Transformer/small-8    7.67kB ± 0%    7.57kB ± 0%  -1.36%  (p=0.000 n=10+10)
Transformer/big-8      49.0kB ± 0%    48.3kB ± 0%  -1.48%  (p=0.000 n=10+10)

name                 old allocs/op  new allocs/op  delta
Transformer/small-8       101 ± 0%        98 ± 0%  -2.97%  (p=0.000 n=10+10)
Transformer/big-8         609 ± 0%       591 ± 1%  -3.00%  (p=0.000 n=10+9)
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
Evgenii Stratonikov 2023-02-24 17:09:34 +03:00 committed by Gitea
parent 9407f30248
commit 25588ee3be

View file

@ -4,7 +4,6 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
"crypto/sha256" "crypto/sha256"
"fmt" "fmt"
"io"
"github.com/TrueCloudLab/frostfs-sdk-go/checksum" "github.com/TrueCloudLab/frostfs-sdk-go/checksum"
"github.com/TrueCloudLab/frostfs-sdk-go/object" "github.com/TrueCloudLab/frostfs-sdk-go/object"
@ -25,8 +24,6 @@ type payloadSizeLimiter struct {
previous []oid.ID previous []oid.ID
chunkWriter io.Writer
splitID *object.SplitID splitID *object.SplitID
parAttrs []object.Attribute parAttrs []object.Attribute
@ -118,21 +115,6 @@ func (s *payloadSizeLimiter) initializeCurrent() {
// create payload hashers // create payload hashers
s.writtenCurrent = 0 s.writtenCurrent = 0
s.initPayloadHashers() s.initPayloadHashers()
// compose multi-writer from target and all payload hashers
ws := make([]io.Writer, 0, 1+len(s.currentHashers)+len(s.parentHashers))
ws = append(ws, s.NextTarget)
for i := range s.currentHashers {
ws = append(ws, s.currentHashers[i].hasher)
}
for i := range s.parentHashers {
ws = append(ws, s.parentHashers[i].hasher)
}
s.chunkWriter = io.MultiWriter(ws...)
} }
func (s *payloadSizeLimiter) initPayloadHashers() { func (s *payloadSizeLimiter) initPayloadHashers() {
@ -269,7 +251,7 @@ func (s *payloadSizeLimiter) writeChunk(chunk []byte) error {
cut = leftToEdge cut = leftToEdge
} }
if _, err := s.chunkWriter.Write(chunk[:cut]); err != nil { if err := s.writeHashes(chunk[:cut]); err != nil {
return fmt.Errorf("could not write chunk to target: %w", err) return fmt.Errorf("could not write chunk to target: %w", err)
} }
@ -285,6 +267,24 @@ func (s *payloadSizeLimiter) writeChunk(chunk []byte) error {
} }
} }
func (s *payloadSizeLimiter) writeHashes(chunk []byte) error {
_, err := s.NextTarget.Write(chunk)
if err != nil {
return err
}
// The `Write` method of `hash.Hash` never returns an error.
for i := range s.currentHashers {
_, _ = s.currentHashers[i].hasher.Write(chunk)
}
for i := range s.parentHashers {
_, _ = s.parentHashers[i].hasher.Write(chunk)
}
return nil
}
func (s *payloadSizeLimiter) prepareFirstChild() { func (s *payloadSizeLimiter) prepareFirstChild() {
// initialize split header with split ID on first object in chain // initialize split header with split ID on first object in chain
s.current.InitRelations() s.current.InitRelations()