erigon-pulse/cmd/state/depths.go

236 lines
4.9 KiB
Go

package main
import (
"bytes"
"fmt"
"github.com/ledgerwatch/turbo-geth/common/dbutils"
"time"
"github.com/ledgerwatch/bolt"
"github.com/ledgerwatch/turbo-geth/crypto"
)
func countDepths() {
startTime := time.Now()
db, err := bolt.Open("/Volumes/tb41/turbo-geth-10/geth/chaindata", 0600, &bolt.Options{ReadOnly: true})
check(err)
defer db.Close()
var occups [64]int // Occupancy of the current level
var counts [64][17]int
var prev [32]byte
count := 0
err = db.View(func(tx *bolt.Tx) error {
b := tx.Bucket(dbutils.AccountsBucket)
if b == nil {
return nil
}
c := b.Cursor()
for k, _ := c.First(); k != nil; k, _ = c.Next() {
if count == 0 {
for i := 0; i < 64; i++ {
occups[i] = 1
}
} else {
// Find the first nibble where k and prev are different
var mask byte = 0xf0
var i int
for i = 0; i < 64; i++ {
idx := i >> 1
if (k[idx] & mask) != (prev[idx] & mask) {
break
}
mask ^= 0xff
}
// Finalise lower nodes
after1 := false
for j := i + 1; j < 64; j++ {
if occups[j] > 1 || !after1 {
counts[j][occups[j]]++
}
if occups[j] == 1 {
after1 = true
} else {
after1 = false
occups[j] = 1
}
}
occups[i]++
}
copy(prev[:], k)
count++
if count%100000 == 0 {
fmt.Printf("Processed %d account records\n", count)
}
}
after1 := false
for j := 0; j < 64; j++ {
if occups[j] > 1 || !after1 {
counts[j][occups[j]]++
}
if occups[j] == 1 {
after1 = true
} else {
after1 = false
occups[j] = 1
}
}
fmt.Printf("Processed %d account records\n", count)
return nil
})
check(err)
nodes := 0
for i := 0; i < 64; i++ {
exists := false
for j := 1; j <= 16; j++ {
if counts[i][j] > 0 {
exists = true
break
}
}
if !exists {
break
}
fmt.Printf("LEVEL %d ==========================\n", i)
for j := 1; j <= 16; j++ {
if counts[i][j] > 0 {
fmt.Printf("%d: %d ", j, counts[i][j])
nodes += counts[i][j]
}
}
fmt.Printf("\n")
}
fmt.Printf("Total number of nodes: %d\n", nodes)
fmt.Printf("Count depth took %s\n", time.Since(startTime))
}
func countStorageDepths() {
startTime := time.Now()
db, err := bolt.Open("/Volumes/tb41/turbo-geth-10/geth/chaindata", 0600, &bolt.Options{ReadOnly: true})
check(err)
defer db.Close()
var occups [64]int // Occupancy of the current level
var counts [64][17]int
var prevAddr [20]byte
var prev [32]byte
var accountExists bool
var filtered int
count := 0
err = db.View(func(tx *bolt.Tx) error {
b := tx.Bucket(dbutils.StorageBucket)
if b == nil {
return nil
}
ab := tx.Bucket(dbutils.AccountsBucket)
if ab == nil {
return nil
}
c := b.Cursor()
for k, _ := c.First(); k != nil; k, _ = c.Next() {
addr := k[:20]
sameAddr := bytes.Equal(addr, prevAddr[:])
if !sameAddr {
copy(prevAddr[:], addr)
v, _ := ab.Get(crypto.Keccak256(addr[:]))
accountExists = v != nil
if !accountExists {
filtered++
}
}
// Filter out storage of non-existent accounts
if !accountExists {
continue
}
key := k[20:52]
if count == 0 {
for i := 0; i < 64; i++ {
occups[i] = 1
}
} else {
if sameAddr {
// Find the first nibble where k and prev are different
var mask byte = 0xf0
var i int
for i = 0; i < 64; i++ {
idx := i >> 1
if (key[idx] & mask) != (prev[idx] & mask) {
break
}
mask ^= 0xff
}
// Finalise lower nodes
after1 := false
for j := i + 1; j < 64; j++ {
if occups[j] > 1 || !after1 {
counts[j][occups[j]]++
}
if occups[j] == 1 {
after1 = true
} else {
after1 = false
occups[j] = 1
}
}
occups[i]++
} else {
after1 := false
for j := 0; j < 64; j++ {
if occups[j] > 1 || !after1 {
counts[j][occups[j]]++
}
if occups[j] == 1 {
after1 = true
} else {
after1 = false
occups[j] = 1
}
}
}
}
copy(prev[:], key)
count++
if count%100000 == 0 {
fmt.Printf("Processed %d storage records, filtered accounts: %d\n", count, filtered)
}
}
after1 := false
for j := 0; j < 64; j++ {
if occups[j] > 1 || !after1 {
counts[j][occups[j]]++
}
if occups[j] == 1 {
after1 = true
} else {
after1 = false
occups[j] = 1
}
}
fmt.Printf("Processed %d storage records, filtered accounts: %d\n", count, filtered)
return nil
})
check(err)
nodes := 0
for i := 0; i < 64; i++ {
exists := false
for j := 1; j <= 16; j++ {
if counts[i][j] > 0 {
exists = true
break
}
}
if !exists {
break
}
fmt.Printf("LEVEL %d ==========================\n", i)
for j := 1; j <= 16; j++ {
if counts[i][j] > 0 {
fmt.Printf("%d: %d ", j, counts[i][j])
nodes += counts[i][j]
}
}
fmt.Printf("\n")
}
fmt.Printf("Total number of nodes: %d\n", nodes)
fmt.Printf("Count depth took %s\n", time.Since(startTime))
}