Small deserialization speedup (#2852)
When walking AriVtx, parsing integers and nibbles actually becomes a hotspot - these trivial changes reduces CPU usage during initial key cache computation by ~15%.
This commit is contained in:
parent
3ea5c531d1
commit
6086c2903c
|
@ -68,10 +68,12 @@ proc deblobify*[T: uint64|VertexID](data: openArray[byte], _: type T): Result[T,
|
|||
if data.len < 1 or data.len > 8:
|
||||
return err(Deblob64LenUnsupported)
|
||||
|
||||
var tmp: array[8, byte]
|
||||
discard tmp.toOpenArray(8 - data.len, 7).copyFrom(data)
|
||||
var tmp = 0'u64
|
||||
let start = 8 - data.len
|
||||
for i in 0..<data.len:
|
||||
tmp += uint64(data[i]) shl (8*(7-(i + start)))
|
||||
|
||||
ok T(uint64.fromBytesBE(tmp))
|
||||
ok T(tmp)
|
||||
|
||||
proc deblobify*(data: openArray[byte], _: type UInt256): Result[UInt256,AristoError] =
|
||||
if data.len < 1 or data.len > 32:
|
||||
|
|
|
@ -78,9 +78,9 @@ func slice*(r: NibblesBuf, ibegin: int, iend = -1): NibblesBuf {.noinit.} =
|
|||
result.iend = e.int8
|
||||
|
||||
func replaceSuffix*(r: NibblesBuf, suffix: NibblesBuf): NibblesBuf =
|
||||
for i in 0..<r.len - suffix.len:
|
||||
for i in 0 ..< r.len - suffix.len:
|
||||
result[i] = r[i]
|
||||
for i in 0..<suffix.len:
|
||||
for i in 0 ..< suffix.len:
|
||||
result[i + r.len - suffix.len] = suffix[i]
|
||||
result.iend = min(64, r.len + suffix.len).int8
|
||||
|
||||
|
@ -122,28 +122,33 @@ func startsWith*(lhs, rhs: NibblesBuf): bool =
|
|||
|
||||
func fromHexPrefix*(
|
||||
T: type NibblesBuf, r: openArray[byte]
|
||||
): tuple[isLeaf: bool, nibbles: NibblesBuf] =
|
||||
): tuple[isLeaf: bool, nibbles: NibblesBuf] {.noinit.} =
|
||||
result.nibbles.ibegin = 0
|
||||
|
||||
if r.len > 0:
|
||||
result.isLeaf = (r[0] and 0x20) != 0
|
||||
let hasOddLen = (r[0] and 0x10) != 0
|
||||
|
||||
var i = 0'i8
|
||||
if hasOddLen:
|
||||
result.nibbles[0] = r[0] and 0x0f
|
||||
i += 1
|
||||
result.nibbles.iend =
|
||||
if hasOddLen:
|
||||
result.nibbles.bytes[0] = r[0] shl 4
|
||||
|
||||
for j in 1 ..< r.len:
|
||||
if i >= 64:
|
||||
break
|
||||
result.nibbles[i] = r[j] shr 4
|
||||
result.nibbles[i + 1] = r[j] and 0x0f
|
||||
i += 2
|
||||
let bytes = min(31, r.len - 1)
|
||||
for j in 0 ..< bytes:
|
||||
result.nibbles.bytes[j] = result.nibbles.bytes[j] or r[j + 1] shr 4
|
||||
result.nibbles.bytes[j + 1] = r[j + 1] shl 4
|
||||
|
||||
result.nibbles.iend = i
|
||||
int8(bytes) * 2 + 1
|
||||
else:
|
||||
let bytes = min(32, r.len - 1)
|
||||
assign(result.nibbles.bytes.toOpenArray(0, bytes - 1), r.toOpenArray(1, bytes))
|
||||
int8(bytes) * 2
|
||||
else:
|
||||
result.isLeaf = false
|
||||
result.nibbles.iend = 0
|
||||
|
||||
func `&`*(a, b: NibblesBuf): NibblesBuf {.noinit.} =
|
||||
result.ibegin = 0
|
||||
for i in 0 ..< a.len:
|
||||
result[i] = a[i]
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import
|
|||
./replay/pp,
|
||||
./test_aristo/test_blobify,
|
||||
./test_aristo/test_merge_proof,
|
||||
./test_aristo/test_nibbles,
|
||||
./test_aristo/test_portal_proof,
|
||||
./test_aristo/test_compute,
|
||||
./test_aristo/[
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
# Nimbus
|
||||
# Copyright (c) 2024 Status Research & Development GmbH
|
||||
# Licensed under either of
|
||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||||
# http://opensource.org/licenses/MIT)
|
||||
# at your option. This file may not be copied, modified, or
|
||||
# distributed except according to those terms.
|
||||
|
||||
{.used.}
|
||||
|
||||
import
|
||||
std/sequtils,
|
||||
stew/byteutils,
|
||||
unittest2,
|
||||
../../nimbus/db/aristo/aristo_desc/desc_nibbles
|
||||
|
||||
suite "Nibbles":
|
||||
test "trivial cases":
|
||||
block:
|
||||
let n = NibblesBuf.fromBytes([])
|
||||
check:
|
||||
n.len == 0
|
||||
block:
|
||||
let n = NibblesBuf.fromBytes([byte 0x10])
|
||||
check:
|
||||
n.len == 2
|
||||
n[0] == 1
|
||||
n[1] == 0
|
||||
$n.slice(1) == "0"
|
||||
$n.slice(2) == ""
|
||||
|
||||
block:
|
||||
let n = NibblesBuf.fromBytes(repeat(byte 0x12, 32))
|
||||
check:
|
||||
n.len == 64
|
||||
n[0] == 1
|
||||
n[63] == 2
|
||||
|
||||
block:
|
||||
let n = NibblesBuf.fromBytes(repeat(byte 0x12, 33))
|
||||
check:
|
||||
n.len == 64
|
||||
n[0] == 1
|
||||
n[63] == 2
|
||||
|
||||
test "to/from hex encoding":
|
||||
block:
|
||||
let n = NibblesBuf.fromBytes([byte 0x12, 0x34, 0x56])
|
||||
|
||||
let
|
||||
he = n.toHexPrefix(true)
|
||||
ho = n.slice(1).toHexPrefix(true)
|
||||
|
||||
check:
|
||||
NibblesBuf.fromHexPrefix(he.data()) == (true, n)
|
||||
NibblesBuf.fromHexPrefix(ho.data()) == (true, n.slice(1))
|
||||
block:
|
||||
let n = NibblesBuf.fromBytes(repeat(byte 0x12, 32))
|
||||
|
||||
let
|
||||
he = n.toHexPrefix(true)
|
||||
ho = n.slice(1).toHexPrefix(true)
|
||||
|
||||
check:
|
||||
NibblesBuf.fromHexPrefix(he.data()) == (true, n)
|
||||
NibblesBuf.fromHexPrefix(ho.data()) == (true, n.slice(1))
|
||||
|
||||
NibblesBuf.fromHexPrefix(@(he.data()) & @[byte 1]) == (true, n)
|
||||
NibblesBuf.fromHexPrefix(@(ho.data()) & @[byte 1]) == (true, n.slice(1))
|
||||
|
||||
test "long":
|
||||
let n = NibblesBuf.fromBytes(
|
||||
hexToSeqByte("0100000000000000000000000000000000000000000000000000000000000000")
|
||||
)
|
||||
|
||||
check $n == "0100000000000000000000000000000000000000000000000000000000000000"
|
||||
check $n.slice(1) == "100000000000000000000000000000000000000000000000000000000000000"
|
||||
|
||||
let
|
||||
he = n.toHexPrefix(true)
|
||||
ho = n.slice(1).toHexPrefix(true)
|
||||
check:
|
||||
NibblesBuf.fromHexPrefix(he.data()) == (true, n)
|
||||
NibblesBuf.fromHexPrefix(ho.data()) == (true, n.slice(1))
|
Loading…
Reference in New Issue