service: Use sync pool for Sign/Verify request headers

```
// Before
BenchmarkSignRequestHeader-8   	     146	   8070375 ns/op	 4210607 B/op	      48 allocs/op
BenchmarkVerifyRequestHeader-8   	      14	  83058325 ns/op	42085955 B/op	    1601 allocs/op

// After
BenchmarkSignRequestHeader-8   	     156	   7709172 ns/op	   33902 B/op	      45 allocs/op
BenchmarkVerifyRequestHeader-8   	      15	  76910232 ns/op	   54368 B/op	    1563 allocs/op

// Summary:
benchmark                          old ns/op     new ns/op     delta
BenchmarkSignRequestHeader-8       8070375       7709172       -4.48%
BenchmarkVerifyRequestHeader-8     83058325      76910232      -7.40%

benchmark                          old allocs     new allocs     delta
BenchmarkSignRequestHeader-8       48             45             -6.25%
BenchmarkVerifyRequestHeader-8     1601           1563           -2.37%

benchmark                          old bytes     new bytes     delta
BenchmarkSignRequestHeader-8       4210607       33902         -99.19%
BenchmarkVerifyRequestHeader-8     42085955      54368         -99.87%
```
This commit is contained in:
Evgeniy Kulikov 2019-12-20 10:13:16 +03:00
parent b76841b4b8
commit 8d028100e9
No known key found for this signature in database
GPG key ID: BF6AEE0A2A699BF2
3 changed files with 84 additions and 5 deletions

View file

@ -2,6 +2,7 @@ package service
import (
"crypto/ecdsa"
"sync"
crypto "github.com/nspcc-dev/neofs-crypto"
"github.com/nspcc-dev/neofs-proto/internal"
@ -12,7 +13,8 @@ import (
type (
// VerifiableRequest adds possibility to sign and verify request header.
VerifiableRequest interface {
Marshal() ([]byte, error)
Size() int
MarshalTo([]byte) (int, error)
AddSignature(*RequestVerificationHeader_Signature)
GetSignatures() []*RequestVerificationHeader_Signature
SetSignatures([]*RequestVerificationHeader_Signature)
@ -133,6 +135,10 @@ func newSignature(key *ecdsa.PrivateKey, data []byte) (*RequestVerificationHeade
}, nil
}
var bytesPool = sync.Pool{New: func() interface{} {
return make([]byte, 4.5*1024*1024) // 4.5MB
}}
// SignRequestHeader receives private key and request with RequestVerificationHeader,
// tries to marshal and sign request with passed PrivateKey, after that adds
// new signature to headers. If something went wrong, returns error.
@ -146,12 +152,23 @@ func SignRequestHeader(key *ecdsa.PrivateKey, msg VerifiableRequest) error {
}()
}
data, err := msg.Marshal()
data := bytesPool.Get().([]byte)
defer func() {
bytesPool.Put(data)
}()
if size := msg.Size(); size <= cap(data) {
data = data[:size]
} else {
data = make([]byte, size)
}
size, err := msg.MarshalTo(data)
if err != nil {
return err
}
signature, err := newSignature(key, data)
signature, err := newSignature(key, data[:size])
if err != nil {
return err
}
@ -174,8 +191,10 @@ func VerifyRequestHeader(msg VerifiableRequest) error {
}()
}
data := bytesPool.Get().([]byte)
signatures := msg.GetSignatures()
defer func() {
bytesPool.Put(data)
msg.SetSignatures(signatures)
}()
@ -189,9 +208,15 @@ func VerifyRequestHeader(msg VerifiableRequest) error {
return errors.Wrapf(ErrCannotLoadPublicKey, "%d: %02x", i, peer)
}
if data, err := msg.Marshal(); err != nil {
if size := msg.Size(); size <= cap(data) {
data = data[:size]
} else {
data = make([]byte, size)
}
if size, err := msg.MarshalTo(data); err != nil {
return errors.Wrapf(err, "%d: %02x", i, peer)
} else if err := crypto.Verify(key, data, sign); err != nil {
} else if err := crypto.Verify(key, data[:size], sign); err != nil {
return errors.Wrapf(err, "%d: %02x", i, peer)
}
}