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:
|
if data.len < 1 or data.len > 8:
|
||||||
return err(Deblob64LenUnsupported)
|
return err(Deblob64LenUnsupported)
|
||||||
|
|
||||||
var tmp: array[8, byte]
|
var tmp = 0'u64
|
||||||
discard tmp.toOpenArray(8 - data.len, 7).copyFrom(data)
|
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] =
|
proc deblobify*(data: openArray[byte], _: type UInt256): Result[UInt256,AristoError] =
|
||||||
if data.len < 1 or data.len > 32:
|
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
|
result.iend = e.int8
|
||||||
|
|
||||||
func replaceSuffix*(r: NibblesBuf, suffix: NibblesBuf): NibblesBuf =
|
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]
|
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[i + r.len - suffix.len] = suffix[i]
|
||||||
result.iend = min(64, r.len + suffix.len).int8
|
result.iend = min(64, r.len + suffix.len).int8
|
||||||
|
|
||||||
|
@ -122,28 +122,33 @@ func startsWith*(lhs, rhs: NibblesBuf): bool =
|
||||||
|
|
||||||
func fromHexPrefix*(
|
func fromHexPrefix*(
|
||||||
T: type NibblesBuf, r: openArray[byte]
|
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:
|
if r.len > 0:
|
||||||
result.isLeaf = (r[0] and 0x20) != 0
|
result.isLeaf = (r[0] and 0x20) != 0
|
||||||
let hasOddLen = (r[0] and 0x10) != 0
|
let hasOddLen = (r[0] and 0x10) != 0
|
||||||
|
|
||||||
var i = 0'i8
|
result.nibbles.iend =
|
||||||
if hasOddLen:
|
if hasOddLen:
|
||||||
result.nibbles[0] = r[0] and 0x0f
|
result.nibbles.bytes[0] = r[0] shl 4
|
||||||
i += 1
|
|
||||||
|
|
||||||
for j in 1 ..< r.len:
|
let bytes = min(31, r.len - 1)
|
||||||
if i >= 64:
|
for j in 0 ..< bytes:
|
||||||
break
|
result.nibbles.bytes[j] = result.nibbles.bytes[j] or r[j + 1] shr 4
|
||||||
result.nibbles[i] = r[j] shr 4
|
result.nibbles.bytes[j + 1] = r[j + 1] shl 4
|
||||||
result.nibbles[i + 1] = r[j] and 0x0f
|
|
||||||
i += 2
|
|
||||||
|
|
||||||
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:
|
else:
|
||||||
result.isLeaf = false
|
result.isLeaf = false
|
||||||
|
result.nibbles.iend = 0
|
||||||
|
|
||||||
func `&`*(a, b: NibblesBuf): NibblesBuf {.noinit.} =
|
func `&`*(a, b: NibblesBuf): NibblesBuf {.noinit.} =
|
||||||
|
result.ibegin = 0
|
||||||
for i in 0 ..< a.len:
|
for i in 0 ..< a.len:
|
||||||
result[i] = a[i]
|
result[i] = a[i]
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import
|
||||||
./replay/pp,
|
./replay/pp,
|
||||||
./test_aristo/test_blobify,
|
./test_aristo/test_blobify,
|
||||||
./test_aristo/test_merge_proof,
|
./test_aristo/test_merge_proof,
|
||||||
|
./test_aristo/test_nibbles,
|
||||||
./test_aristo/test_portal_proof,
|
./test_aristo/test_portal_proof,
|
||||||
./test_aristo/test_compute,
|
./test_aristo/test_compute,
|
||||||
./test_aristo/[
|
./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