core: optimize storageFind
Because `Map` stores elements in arbitrary order, addition of new element takes linear time (`Index` iterates over all keys). Thus our `storageFind` is actually quadratic in time. Optimize this by creating map from sorted slice. ``` name old time/op new time/op delta StorageFind-8 157µs ± 2% 112µs ± 1% -28.60% (p=0.000 n=10+10) name old alloc/op new alloc/op delta StorageFind-8 69.4kB ± 0% 60.5kB ± 0% -12.90% (p=0.000 n=9+10) name old allocs/op new allocs/op delta StorageFind-8 2.21k ± 0% 2.00k ± 0% -9.37% (p=0.000 n=10+7) ``` Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
b8b272c8c4
commit
eb7bd7b99b
1 changed files with 13 additions and 8 deletions
|
@ -192,18 +192,23 @@ func storageFind(ic *interop.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
filteredMap := stackitem.NewMap()
|
arr := make([]stackitem.MapElement, 0, len(siMap))
|
||||||
for k, v := range siMap {
|
for k, v := range siMap {
|
||||||
key := append(prefix, []byte(k)...)
|
keycopy := make([]byte, len(k)+len(prefix))
|
||||||
keycopy := make([]byte, len(key))
|
copy(keycopy, prefix)
|
||||||
copy(keycopy, key)
|
copy(keycopy[len(prefix):], k)
|
||||||
filteredMap.Add(stackitem.NewByteArray(keycopy), stackitem.NewByteArray(v))
|
arr = append(arr, stackitem.MapElement{
|
||||||
|
Key: stackitem.NewByteArray(keycopy),
|
||||||
|
Value: stackitem.NewByteArray(v),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
sort.Slice(filteredMap.Value().([]stackitem.MapElement), func(i, j int) bool {
|
sort.Slice(arr, func(i, j int) bool {
|
||||||
return bytes.Compare(filteredMap.Value().([]stackitem.MapElement)[i].Key.Value().([]byte),
|
k1 := arr[i].Key.Value().([]byte)
|
||||||
filteredMap.Value().([]stackitem.MapElement)[j].Key.Value().([]byte)) == -1
|
k2 := arr[j].Key.Value().([]byte)
|
||||||
|
return bytes.Compare(k1, k2) == -1
|
||||||
})
|
})
|
||||||
|
|
||||||
|
filteredMap := stackitem.NewMapWithValue(arr)
|
||||||
item := istorage.NewIterator(filteredMap, len(prefix), opts)
|
item := istorage.NewIterator(filteredMap, len(prefix), opts)
|
||||||
ic.VM.Estack().PushVal(stackitem.NewInterop(item))
|
ic.VM.Estack().PushVal(stackitem.NewInterop(item))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue