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 (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/ethereum/go-ethereum/hook"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -186,7 +187,13 @@ func (f *Freezer) Close() error {
|
||||||
// in the freezer.
|
// in the freezer.
|
||||||
func (f *Freezer) HasAncient(kind string, number uint64) (bool, error) {
|
func (f *Freezer) HasAncient(kind string, number uint64) (bool, error) {
|
||||||
if table := f.tables[kind]; table != nil {
|
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
|
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.
|
// Ancient retrieves an ancient binary blob from the append-only immutable files.
|
||||||
func (f *Freezer) Ancient(kind string, number uint64) ([]byte, error) {
|
func (f *Freezer) Ancient(kind string, number uint64) ([]byte, error) {
|
||||||
if table := f.tables[kind]; table != nil {
|
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
|
return nil, errUnknownTable
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ package leveldb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/ethereum/go-ethereum/hook"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -185,11 +186,13 @@ func (db *Database) Close() error {
|
||||||
|
|
||||||
// Has retrieves if a key is present in the key-value store.
|
// Has retrieves if a key is present in the key-value store.
|
||||||
func (db *Database) Has(key []byte) (bool, error) {
|
func (db *Database) Has(key []byte) (bool, error) {
|
||||||
|
hook.Gr.CountLevelDbRead(key)
|
||||||
return db.db.Has(key, nil)
|
return db.db.Has(key, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get retrieves the given key if it's present in the key-value store.
|
// Get retrieves the given key if it's present in the key-value store.
|
||||||
func (db *Database) Get(key []byte) ([]byte, error) {
|
func (db *Database) Get(key []byte) ([]byte, error) {
|
||||||
|
hook.Gr.CountLevelDbRead(key)
|
||||||
dat, err := db.db.Get(key, nil)
|
dat, err := db.db.Get(key, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// Has retrieves if a key is present in the snapshot backing by a key-value
|
||||||
// data store.
|
// data store.
|
||||||
func (snap *snapshot) Has(key []byte) (bool, error) {
|
func (snap *snapshot) Has(key []byte) (bool, error) {
|
||||||
|
hook.Gr.CountLevelDbSnapshotRead(key)
|
||||||
return snap.db.Has(key, nil)
|
return snap.db.Has(key, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get retrieves the given key if it's present in the snapshot backing by
|
// Get retrieves the given key if it's present in the snapshot backing by
|
||||||
// key-value data store.
|
// key-value data store.
|
||||||
func (snap *snapshot) Get(key []byte) ([]byte, error) {
|
func (snap *snapshot) Get(key []byte) ([]byte, error) {
|
||||||
|
hook.Gr.CountLevelDbSnapshotRead(key)
|
||||||
return snap.db.Get(key, nil)
|
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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"github.com/ethereum/go-ethereum/hook"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -509,8 +510,15 @@ func (h *handler) handleCall(cp *callProc, msg *jsonrpcMessage) *jsonrpcMessage
|
||||||
return msg.errorResponse(&invalidParamsError{err.Error()})
|
return msg.errorResponse(&invalidParamsError{err.Error()})
|
||||||
}
|
}
|
||||||
start := time.Now()
|
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.
|
// Collect the statistics for RPC calls if metrics is enabled.
|
||||||
// We only care about pure rpc call. Filter out subscription.
|
// We only care about pure rpc call. Filter out subscription.
|
||||||
if callb != h.unsubscribeCb {
|
if callb != h.unsubscribeCb {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue