mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
Hook RPC call and record DB read operation count
This commit is contained in:
parent
0809c46266
commit
522c63cc3a
4 changed files with 159 additions and 3 deletions
|
|
@ -19,6 +19,7 @@ package rawdb
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/ethereum/go-ethereum/hook"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
|
@ -186,7 +187,13 @@ func (f *Freezer) Close() error {
|
|||
// in the freezer.
|
||||
func (f *Freezer) HasAncient(kind string, number uint64) (bool, error) {
|
||||
if table := f.tables[kind]; table != nil {
|
||||
return table.has(number), nil
|
||||
if table.has(number) {
|
||||
bytes, err := table.Retrieve(number)
|
||||
if len(bytes) > 0 && err != nil {
|
||||
hook.Gr.CountAncientDbRead(bytes)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
|
@ -194,7 +201,11 @@ func (f *Freezer) HasAncient(kind string, number uint64) (bool, error) {
|
|||
// Ancient retrieves an ancient binary blob from the append-only immutable files.
|
||||
func (f *Freezer) Ancient(kind string, number uint64) ([]byte, error) {
|
||||
if table := f.tables[kind]; table != nil {
|
||||
return table.Retrieve(number)
|
||||
bytes, err := table.Retrieve(number)
|
||||
if len(bytes) > 0 && err != nil {
|
||||
hook.Gr.CountAncientDbRead(bytes)
|
||||
}
|
||||
return bytes, err
|
||||
}
|
||||
return nil, errUnknownTable
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ package leveldb
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ethereum/go-ethereum/hook"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
|
@ -185,11 +186,13 @@ func (db *Database) Close() error {
|
|||
|
||||
// Has retrieves if a key is present in the key-value store.
|
||||
func (db *Database) Has(key []byte) (bool, error) {
|
||||
hook.Gr.CountLevelDbRead(key)
|
||||
return db.db.Has(key, nil)
|
||||
}
|
||||
|
||||
// Get retrieves the given key if it's present in the key-value store.
|
||||
func (db *Database) Get(key []byte) ([]byte, error) {
|
||||
hook.Gr.CountLevelDbRead(key)
|
||||
dat, err := db.db.Get(key, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -469,12 +472,14 @@ type snapshot struct {
|
|||
// Has retrieves if a key is present in the snapshot backing by a key-value
|
||||
// data store.
|
||||
func (snap *snapshot) Has(key []byte) (bool, error) {
|
||||
hook.Gr.CountLevelDbSnapshotRead(key)
|
||||
return snap.db.Has(key, nil)
|
||||
}
|
||||
|
||||
// Get retrieves the given key if it's present in the snapshot backing by
|
||||
// key-value data store.
|
||||
func (snap *snapshot) Get(key []byte) ([]byte, error) {
|
||||
hook.Gr.CountLevelDbSnapshotRead(key)
|
||||
return snap.db.Get(key, nil)
|
||||
}
|
||||
|
||||
|
|
|
|||
132
hook/record.go
Normal file
132
hook/record.go
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
package hook
|
||||
|
||||
import "sync"
|
||||
|
||||
type Record struct {
|
||||
ancientDbReadCnt int // ancient DB 접근 횟수
|
||||
levelDbReadCnt int // level DB 접근 횟수
|
||||
levelDbSnapshotReadCnt int // level DB 스냅샷 접근 횟수
|
||||
duplicatedReadCnt int // 중복 디비 접근 횟수
|
||||
duplicatedSnapshotReadCnt int // 중복 스냅샷 접근 횟수
|
||||
readDbKeySet *map[string]bool
|
||||
readDbKeySetLock sync.RWMutex
|
||||
readSnapshotDbKeySet *map[string]bool
|
||||
readSnapshotDbKeySetLock sync.RWMutex
|
||||
rpcLock sync.Mutex
|
||||
}
|
||||
|
||||
var Gr = Record{
|
||||
ancientDbReadCnt: 0,
|
||||
levelDbReadCnt: 0,
|
||||
levelDbSnapshotReadCnt: 0,
|
||||
duplicatedReadCnt: 0,
|
||||
duplicatedSnapshotReadCnt: 0,
|
||||
readDbKeySet: &map[string]bool{},
|
||||
readDbKeySetLock: sync.RWMutex{},
|
||||
readSnapshotDbKeySet: &map[string]bool{},
|
||||
readSnapshotDbKeySetLock: sync.RWMutex{},
|
||||
rpcLock: sync.Mutex{},
|
||||
}
|
||||
|
||||
func (gr *Record) Lock() {
|
||||
gr.rpcLock.Lock()
|
||||
}
|
||||
|
||||
func (gr *Record) Unlock() {
|
||||
gr.rpcLock.Unlock()
|
||||
}
|
||||
|
||||
func (gr *Record) Reset() {
|
||||
gr.ancientDbReadCnt = 0
|
||||
gr.levelDbReadCnt = 0
|
||||
gr.levelDbSnapshotReadCnt = 0
|
||||
gr.duplicatedReadCnt = 0
|
||||
gr.duplicatedSnapshotReadCnt = 0
|
||||
gr.readDbKeySet = &map[string]bool{}
|
||||
gr.readSnapshotDbKeySet = &map[string]bool{}
|
||||
}
|
||||
|
||||
func (gr *Record) addReadKeySet(key string) {
|
||||
gr.readDbKeySetLock.Lock()
|
||||
defer gr.readDbKeySetLock.Unlock()
|
||||
|
||||
(*gr.readDbKeySet)[key] = true
|
||||
}
|
||||
|
||||
func (gr *Record) addReadSnapshotKeySet(key string) {
|
||||
gr.readSnapshotDbKeySetLock.Lock()
|
||||
defer gr.readSnapshotDbKeySetLock.Unlock()
|
||||
|
||||
(*gr.readSnapshotDbKeySet)[key] = true
|
||||
}
|
||||
|
||||
func (gr *Record) isAlreadyRead(key string) bool {
|
||||
gr.readDbKeySetLock.RLock()
|
||||
defer gr.readDbKeySetLock.RUnlock()
|
||||
if (*gr.readDbKeySet)[key] == true {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (gr *Record) countDuplicatedKey(key []byte) {
|
||||
keyStr := string(key[:])
|
||||
if gr.isAlreadyRead(keyStr) {
|
||||
gr.duplicatedReadCnt++
|
||||
} else {
|
||||
gr.addReadKeySet(keyStr)
|
||||
}
|
||||
}
|
||||
|
||||
func (gr *Record) isAlreadyReadSnapshot(key string) bool {
|
||||
gr.readSnapshotDbKeySetLock.RLock()
|
||||
defer gr.readSnapshotDbKeySetLock.RUnlock()
|
||||
if (*gr.readSnapshotDbKeySet)[key] == true {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (gr *Record) countDuplicatedSnapshotKey(key []byte) {
|
||||
keyStr := string(key[:])
|
||||
if gr.isAlreadyReadSnapshot(keyStr) {
|
||||
gr.duplicatedSnapshotReadCnt++
|
||||
} else {
|
||||
gr.addReadSnapshotKeySet(keyStr)
|
||||
}
|
||||
}
|
||||
|
||||
func (gr *Record) CountAncientDbRead(key []byte) {
|
||||
gr.countDuplicatedKey(key)
|
||||
gr.ancientDbReadCnt++
|
||||
}
|
||||
|
||||
func (gr *Record) CountLevelDbRead(key []byte) {
|
||||
gr.countDuplicatedKey(key)
|
||||
gr.levelDbReadCnt++
|
||||
}
|
||||
|
||||
func (gr *Record) CountLevelDbSnapshotRead(key []byte) {
|
||||
gr.countDuplicatedSnapshotKey(key)
|
||||
gr.levelDbSnapshotReadCnt++
|
||||
}
|
||||
|
||||
func (gr *Record) AncientDbReadCnt() int {
|
||||
return gr.ancientDbReadCnt
|
||||
}
|
||||
|
||||
func (gr *Record) LevelDbReadCnt() int {
|
||||
return gr.levelDbReadCnt
|
||||
}
|
||||
|
||||
func (gr *Record) LevelDbSnapshotReadCnt() int {
|
||||
return gr.levelDbSnapshotReadCnt
|
||||
}
|
||||
|
||||
func (gr *Record) DuplicatedReadCnt() int {
|
||||
return gr.duplicatedReadCnt
|
||||
}
|
||||
|
||||
func (gr *Record) DuplicatedSnapshotReadCnt() int {
|
||||
return gr.duplicatedSnapshotReadCnt
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ package rpc
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/ethereum/go-ethereum/hook"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -509,8 +510,15 @@ func (h *handler) handleCall(cp *callProc, msg *jsonrpcMessage) *jsonrpcMessage
|
|||
return msg.errorResponse(&invalidParamsError{err.Error()})
|
||||
}
|
||||
start := time.Now()
|
||||
answer := h.runMethod(cp.ctx, msg, callb, args)
|
||||
|
||||
hook.Gr.Lock()
|
||||
hook.Gr.Reset()
|
||||
h.log.Error("Before runMethod", "msg.Method", msg.Method, "args", args)
|
||||
answer := h.runMethod(cp.ctx, msg, callb, args)
|
||||
h.log.Error("Result", "levelDb", hook.Gr.LevelDbReadCnt(), "levelDb duplicated", hook.Gr.DuplicatedReadCnt(), "levelDbSnapshot", hook.Gr.LevelDbSnapshotReadCnt(), "levelDbSnapshot duplicated", hook.Gr.DuplicatedSnapshotReadCnt(), "ancientDb", hook.Gr.AncientDbReadCnt())
|
||||
h.log.Error("Statistics", "levelDbNewRead", hook.Gr.LevelDbReadCnt()-hook.Gr.DuplicatedReadCnt(), "levelDbSnapshotNewRead", hook.Gr.LevelDbSnapshotReadCnt()-hook.Gr.DuplicatedSnapshotReadCnt(), "ancientDbRead", hook.Gr.AncientDbReadCnt())
|
||||
h.log.Error("After runMethod", "msg.Method", msg.Method, "args", args)
|
||||
hook.Gr.Unlock()
|
||||
// Collect the statistics for RPC calls if metrics is enabled.
|
||||
// We only care about pure rpc call. Filter out subscription.
|
||||
if callb != h.unsubscribeCb {
|
||||
|
|
|
|||
Loading…
Reference in a new issue