erigon-pulse/common/dbutils/helper.go
Alex Sharov daa359c363
Mgr schedule iterator (#566)
* db based version of PrefixByCumulativeWitnessSize

* db based version of PrefixByCumulativeWitnessSize

* retain all in Trie by default

* fix WitnessLen logic in calcTrie roots

* Rename IntermediateTrieWitnessLenBucket to IntermediateWitnessLenBucket

* handle corner cases in WL

* Use correct incarnation for IH bucket

* use name WitnessSize

* save progress towards db-only witness estimation

* results from trie and from db are still different

* less recursion

* correct incarnation in CumulativeSearch

* reuse results from previous Tick, separate concepts of parent and startKey

* experiment: if not including trie structure to WitnessSize will reduce cumulative error

* tool to generate all IH and tool to calculate assessment of cumulative error

* tool to generate all IH

* Calculate totalWitnessSize based on DB data - then schedule will not overrun state during MGR cycle

* better stats

* Calculate totalWitnessSize based on DB data - then schedule will not overrun state during MGR cycle

* Calculate totalWitnessSize based on DB data - then schedule will not overrun state during MGR cycle

* calculate ticks size distribution

* estimate cumulative error

* fix linter

* resetIH from scratch if needed

* cleanup

* fix test

* fix test
2020-05-28 12:33:05 +01:00

80 lines
1.6 KiB
Go

package dbutils
import (
"bytes"
)
// EncodeTimestamp has the property: if a < b, then Encoding(a) < Encoding(b) lexicographically
func EncodeTimestamp(timestamp uint64) []byte {
var suffix []byte
var limit uint64 = 32
for bytecount := 1; bytecount <= 8; bytecount++ {
if timestamp < limit {
suffix = make([]byte, bytecount)
b := timestamp
for i := bytecount - 1; i > 0; i-- {
suffix[i] = byte(b & 0xff)
b >>= 8
}
suffix[0] = byte(b) | (byte(bytecount) << 5) // 3 most significant bits of the first byte are bytecount
break
}
limit <<= 8
}
return suffix
}
func DecodeTimestamp(suffix []byte) (uint64, []byte) {
bytecount := int(suffix[0] >> 5)
timestamp := uint64(suffix[0] & 0x1f)
for i := 1; i < bytecount; i++ {
timestamp = (timestamp << 8) | uint64(suffix[i])
}
return timestamp, suffix[bytecount:]
}
func ChangeSetByIndexBucket(b []byte) []byte {
if bytes.Equal(b, AccountsHistoryBucket) {
return AccountChangeSetBucket
}
if bytes.Equal(b, StorageHistoryBucket) {
return StorageChangeSetBucket
}
panic("wrong bucket")
}
// NextSubtree does []byte++. Returns false if overflow.
func NextSubtree(in []byte) ([]byte, bool) {
r := make([]byte, len(in))
copy(r, in)
for i := len(r) - 1; i >= 0; i-- {
if r[i] != 255 {
r[i]++
return r, true
}
r[i] = 0
}
return nil, false
}
func NextS(in []byte, out *[]byte) bool {
tmp := *out
if cap(tmp) < len(in) {
tmp = make([]byte, len(in))
}
tmp = tmp[:len(in)]
copy(tmp, in)
for i := len(tmp) - 1; i >= 0; i-- {
if tmp[i] != 255 {
tmp[i]++
*out = tmp
return true
}
tmp[i] = 0
}
*out = tmp
return false
}