[#31] fstree: Speedup string-to-address conversion

```
name                  old time/op    new time/op    delta
_addressFromString-8    1.25µs ±30%    1.02µs ± 6%  -18.49%  (p=0.000 n=9+9)

name                  old alloc/op   new alloc/op   delta
_addressFromString-8      352B ± 0%      256B ± 0%  -27.27%  (p=0.000 n=9+10)

name                  old allocs/op  new allocs/op  delta
_addressFromString-8      6.00 ± 0%      4.00 ± 0%  -33.33%  (p=0.000
n=10+10)
```

Also, assure compiler that `s` doesn't escape:
Before this commit:
```
./fstree.go:74:24: leaking param: s
./fstree.go:90:6: moved to heap: addr
```

After this commit:
```
./fstree.go:74:24: s does not escape
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
Evgenii Stratonikov 2023-02-10 07:59:15 +03:00 committed by fyrchik
parent ab21d90cfb
commit abbecf49d6
2 changed files with 27 additions and 13 deletions

View file

@ -71,27 +71,27 @@ func stringifyAddress(addr oid.Address) string {
return addr.Object().EncodeToString() + "." + addr.Container().EncodeToString()
}
func addressFromString(s string) (*oid.Address, error) {
ss := strings.SplitN(s, ".", 2)
if len(ss) != 2 {
return nil, errors.New("invalid address")
func addressFromString(s string) (oid.Address, error) {
i := strings.IndexByte(s, '.')
if i == -1 {
return oid.Address{}, errors.New("invalid address")
}
var obj oid.ID
if err := obj.DecodeString(ss[0]); err != nil {
return nil, err
if err := obj.DecodeString(s[:i]); err != nil {
return oid.Address{}, err
}
var cnr cid.ID
if err := cnr.DecodeString(ss[1]); err != nil {
return nil, err
if err := cnr.DecodeString(s[i+1:]); err != nil {
return oid.Address{}, err
}
var addr oid.Address
addr.SetObject(obj)
addr.SetContainer(cnr)
return &addr, nil
return addr, nil
}
// Iterate iterates over all stored objects.
@ -135,7 +135,7 @@ func (t *FSTree) iterate(depth uint64, curPath []string, prm common.IteratePrm)
}
if prm.LazyHandler != nil {
err = prm.LazyHandler(*addr, func() ([]byte, error) {
err = prm.LazyHandler(addr, func() ([]byte, error) {
return os.ReadFile(filepath.Join(curPath...))
})
} else {
@ -147,7 +147,7 @@ func (t *FSTree) iterate(depth uint64, curPath []string, prm common.IteratePrm)
if err != nil {
if prm.IgnoreErrors {
if prm.ErrorHandler != nil {
return prm.ErrorHandler(*addr, err)
return prm.ErrorHandler(addr, err)
}
continue
}
@ -155,7 +155,7 @@ func (t *FSTree) iterate(depth uint64, curPath []string, prm common.IteratePrm)
}
err = prm.Handler(common.IterationElement{
Address: *addr,
Address: addr,
ObjectData: data,
StorageID: []byte{},
})

View file

@ -12,5 +12,19 @@ func TestAddressToString(t *testing.T) {
s := stringifyAddress(addr)
actual, err := addressFromString(s)
require.NoError(t, err)
require.Equal(t, addr, *actual)
require.Equal(t, addr, actual)
}
func Benchmark_addressFromString(b *testing.B) {
addr := oidtest.Address()
s := stringifyAddress(addr)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := addressFromString(s)
if err != nil {
b.Fatalf("benchmark error: %v", err)
}
}
}