diff --git a/mempool/mempool.go b/mempool/mempool.go index 0744880a1..46e71f4e8 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -77,6 +77,10 @@ func NewMempool(proxyAppConn proxy.AppConn) *Mempool { return mempool } +func (mem *Mempool) Size() int { + return mem.txs.Len() +} + // Return the first element of mem.txs for peer goroutines to call .NextWait() on. // Blocks until txs has elements. func (mem *Mempool) TxsFrontWait() *clist.CElement { diff --git a/rpc/core/dev.go b/rpc/core/dev.go new file mode 100644 index 000000000..a7a5c54df --- /dev/null +++ b/rpc/core/dev.go @@ -0,0 +1,56 @@ +package core + +import ( + "fmt" + "os" + "runtime/pprof" + "strconv" + + ctypes "github.com/tendermint/tendermint/rpc/core/types" +) + +func UnsafeSetConfig(typ, key, value string) (*ctypes.ResultUnsafeSetConfig, error) { + switch typ { + case "string": + config.Set(key, value) + case "int": + val, err := strconv.Atoi(value) + if err != nil { + return nil, fmt.Errorf("non-integer value found. key:%s; value:%s; err:%v", key, value, err) + } + config.Set(key, val) + case "bool": + switch value { + case "true": + config.Set(key, true) + case "false": + config.Set(key, false) + default: + return nil, fmt.Errorf("bool value must be true or false. got %s", value) + } + default: + return nil, fmt.Errorf("Unknown type %s", typ) + } + return &ctypes.ResultUnsafeSetConfig{}, nil +} + +var profFile *os.File + +func UnsafeStartCPUProfiler(filename string) (*ctypes.ResultUnsafeCPUProfiler, error) { + var err error + profFile, err = os.Create(filename) + if err != nil { + return nil, err + } + err = pprof.StartCPUProfile(profFile) + if err != nil { + return nil, err + } + return &ctypes.ResultUnsafeCPUProfiler{}, nil +} + +func UnsafeStopCPUProfiler() (*ctypes.ResultUnsafeCPUProfiler, error) { + pprof.StopCPUProfile() + profFile.Close() + return &ctypes.ResultUnsafeCPUProfiler{}, nil +} diff --git a/rpc/core/mempool.go b/rpc/core/mempool.go index e10c72660..d06fca8b2 100644 --- a/rpc/core/mempool.go +++ b/rpc/core/mempool.go @@ -41,6 +41,5 @@ func UnconfirmedTxs() (*ctypes.ResultUnconfirmedTxs, error) { } func NumUnconfirmedTxs() (*ctypes.ResultUnconfirmedTxs, error) { - txs := mempoolReactor.Mempool.Reap() - return &ctypes.ResultUnconfirmedTxs{len(txs), txs[:0]}, nil + return &ctypes.ResultUnconfirmedTxs{N: mempoolReactor.Mempool.Size()}, nil } diff --git a/rpc/core/routes.go b/rpc/core/routes.go index 5a4987da5..b642ad7fe 100644 --- a/rpc/core/routes.go +++ b/rpc/core/routes.go @@ -24,7 +24,9 @@ var Routes = map[string]*rpc.RPCFunc{ "unconfirmed_txs": rpc.NewRPCFunc(UnconfirmedTxsResult, ""), "num_unconfirmed_txs": rpc.NewRPCFunc(NumUnconfirmedTxsResult, ""), - "unsafe_set_config": rpc.NewRPCFunc(UnsafeSetConfigResult, "type,key,value"), + "unsafe_set_config": rpc.NewRPCFunc(UnsafeSetConfigResult, "type,key,value"), + "unsafe_start_cpu_profiler": rpc.NewRPCFunc(UnsafeStartCPUProfilerResult, "filename"), + "unsafe_stop_cpu_profiler": rpc.NewRPCFunc(UnsafeStopCPUProfilerResult, ""), } func SubscribeResult(wsCtx rpctypes.WSRPCContext, event string) (ctypes.TMResult, error) { @@ -146,3 +148,19 @@ func UnsafeSetConfigResult(typ, key, value string) (ctypes.TMResult, error) { return r, nil } } + +func UnsafeStartCPUProfilerResult(filename string) (ctypes.TMResult, error) { + if r, err := UnsafeStartCPUProfiler(filename); err != nil { + return nil, err + } else { + return r, nil + } +} + +func UnsafeStopCPUProfilerResult() (ctypes.TMResult, error) { + if r, err := UnsafeStopCPUProfiler(); err != nil { + return nil, err + } else { + return r, nil + } +} diff --git a/rpc/core/status.go b/rpc/core/status.go index 8f056fd4e..bf3d69ffe 100644 --- a/rpc/core/status.go +++ b/rpc/core/status.go @@ -1,9 +1,6 @@ package core import ( - "fmt" - "strconv" - ctypes "github.com/tendermint/tendermint/rpc/core/types" "github.com/tendermint/tendermint/types" ) @@ -31,28 +28,3 @@ func Status() (*ctypes.ResultStatus, error) { LatestBlockHeight: latestHeight, LatestBlockTime: latestBlockTime}, nil } - -func UnsafeSetConfig(typ, key, value string) (*ctypes.ResultUnsafeSetConfig, error) { - switch typ { - case "string": - config.Set(key, value) - case "int": - val, err := strconv.Atoi(value) - if err != nil { - return nil, fmt.Errorf("non-integer value found. key:%s; value:%s; err:%v", key, value, err) - } - config.Set(key, val) - case "bool": - switch value { - case "true": - config.Set(key, true) - case "false": - config.Set(key, false) - default: - return nil, fmt.Errorf("bool value must be true or false. got %s", value) - } - default: - return nil, fmt.Errorf("Unknown type %s", typ) - } - return &ctypes.ResultUnsafeSetConfig{}, nil -} diff --git a/rpc/core/types/responses.go b/rpc/core/types/responses.go index 660c6e0c1..ee7307a26 100644 --- a/rpc/core/types/responses.go +++ b/rpc/core/types/responses.go @@ -70,6 +70,8 @@ type ResultUnconfirmedTxs struct { type ResultUnsafeSetConfig struct{} +type ResultUnsafeCPUProfiler struct{} + type ResultSubscribe struct { } @@ -109,7 +111,9 @@ const ( ResultTypeEvent = byte(0x82) // 0xa bytes for testing - ResultTypeUnsafeSetConfig = byte(0xa0) + ResultTypeUnsafeSetConfig = byte(0xa0) + ResultTypeUnsafeStartCPUProfiler = byte(0xa1) + ResultTypeUnsafeStopCPUProfiler = byte(0xa2) ) type TMResult interface { @@ -133,4 +137,6 @@ var _ = wire.RegisterInterface( wire.ConcreteType{&ResultUnsubscribe{}, ResultTypeUnsubscribe}, wire.ConcreteType{&ResultEvent{}, ResultTypeEvent}, wire.ConcreteType{&ResultUnsafeSetConfig{}, ResultTypeUnsafeSetConfig}, + wire.ConcreteType{&ResultUnsafeCPUProfiler{}, ResultTypeUnsafeStartCPUProfiler}, + wire.ConcreteType{&ResultUnsafeCPUProfiler{}, ResultTypeUnsafeStopCPUProfiler}, )