erigon-pulse/cmd/state/stats/index_stats.go

134 lines
3.2 KiB
Go

package stats
import (
"bytes"
"encoding/csv"
"fmt"
"log"
"os"
"sort"
"strconv"
"strings"
"time"
"github.com/ledgerwatch/erigon/common"
"github.com/ledgerwatch/erigon/common/dbutils"
"github.com/ledgerwatch/erigon/ethdb/kv"
)
func IndexStats(chaindata string, indexBucket string, statsFile string) error {
db := kv.MustOpen(chaindata)
startTime := time.Now()
lenOfKey := common.HashLength
if strings.HasPrefix(indexBucket, dbutils.StorageHistoryBucket) {
lenOfKey = common.HashLength*2 + common.IncarnationLength
}
more1index := 0
more10index := make(map[string]uint64)
more50index := make(map[string]uint64)
more100index := make(map[string]uint64)
more200index := make(map[string]uint64)
more500index := make(map[string]uint64)
more1000index := make(map[string]uint64)
prevKey := []byte{}
count := uint64(1)
added := false
i := uint64(0)
if err := db.Walk(indexBucket, []byte{}, 0, func(k, v []byte) (b bool, e error) {
if i%100_000 == 0 {
fmt.Printf("Processed %dK, %s\n", i/1000, time.Since(startTime))
}
if bytes.Equal(k[:lenOfKey], prevKey) {
count++
if count > 1 && !added {
more1index++
added = true
}
if count > 10 {
more10index[string(common.CopyBytes(k[:lenOfKey]))] = count
}
if count > 50 {
more50index[string(common.CopyBytes(k[:lenOfKey]))] = count
}
if count > 100 {
more100index[string(common.CopyBytes(k[:lenOfKey]))] = count
}
if count > 200 {
more200index[string(common.CopyBytes(k[:lenOfKey]))] = count
}
if count > 500 {
more500index[string(common.CopyBytes(k[:lenOfKey]))] = count
}
if count > 1000 {
more1000index[string(common.CopyBytes(k[:lenOfKey]))] = count
}
} else {
added = false
count = 1
prevKey = common.CopyBytes(k[:common.HashLength])
}
return true, nil
}); err != nil {
return err
}
fmt.Println("more1", more1index)
fmt.Println("more10", len(more10index))
fmt.Println("more50", len(more50index))
fmt.Println("more100", len(more100index))
fmt.Println("more200", len(more200index))
fmt.Println("more500", len(more500index))
fmt.Println("more1000", len(more1000index))
if statsFile != "" {
f, err := os.Create(statsFile)
if err != nil {
log.Fatal(err)
}
defer f.Close() //nolint
save10 := make([]struct {
Address string
Hash string
NumOfIndexes uint64
}, 0, len(more10index))
for hash, v := range more10index {
p, innerErr := db.Get(dbutils.PreimagePrefix, []byte(hash)[:common.HashLength])
if innerErr != nil {
return innerErr
}
if len(p) == 0 {
p = make([]byte, 20)
}
save10 = append(save10, struct {
Address string
Hash string
NumOfIndexes uint64
}{
Address: common.BytesToAddress(p).String(),
NumOfIndexes: v,
Hash: common.Bytes2Hex([]byte(hash)),
})
}
sort.Slice(save10, func(i, j int) bool {
return save10[i].NumOfIndexes > save10[j].NumOfIndexes
})
csvWriter := csv.NewWriter(f)
err = csvWriter.Write([]string{"hash", "address", "num"})
if err != nil {
return err
}
for _, v := range save10 {
err = csvWriter.Write([]string{v.Hash, v.Address, strconv.FormatUint(v.NumOfIndexes, 10)})
if err != nil {
return err
}
}
}
return nil
}