From b8cd5209279a8ae3b062cf97ecc81c04f34a161a Mon Sep 17 00:00:00 2001 From: MathxH Chen Date: Thu, 24 Jun 2021 05:46:07 +0800 Subject: [PATCH 1/2] [p2p] Try to fix P2P memory issue (#3795) * [p2p] Fix context leak in resolveMultiAddr * [p2p] upgrade go-libp2p-kad-dht to v0.12.1 * [p2p] Upgrade entire libp2p stack --- go.mod | 6 +++--- p2p/types/peerAddr.go | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 0e1471c61..32c173716 100644 --- a/go.mod +++ b/go.mod @@ -30,12 +30,12 @@ require ( github.com/hashicorp/golang-lru v0.5.4 github.com/ipfs/go-ds-badger v0.2.4 github.com/json-iterator/go v1.1.10 - github.com/libp2p/go-libp2p v0.14.0 + github.com/libp2p/go-libp2p v0.14.2 github.com/libp2p/go-libp2p-core v0.8.5 github.com/libp2p/go-libp2p-crypto v0.1.0 github.com/libp2p/go-libp2p-discovery v0.5.0 - github.com/libp2p/go-libp2p-kad-dht v0.11.1 - github.com/libp2p/go-libp2p-pubsub v0.4.0 + github.com/libp2p/go-libp2p-kad-dht v0.12.1 + github.com/libp2p/go-libp2p-pubsub v0.4.1 github.com/multiformats/go-multiaddr v0.3.1 github.com/multiformats/go-multiaddr-dns v0.3.1 github.com/natefinch/lumberjack v2.0.0+incompatible diff --git a/p2p/types/peerAddr.go b/p2p/types/peerAddr.go index f3e0c7e94..724a37269 100644 --- a/p2p/types/peerAddr.go +++ b/p2p/types/peerAddr.go @@ -86,7 +86,8 @@ func resolveMultiAddrString(addrStr string) ([]libp2p_peer.AddrInfo, error) { func resolveMultiAddr(raw ma.Multiaddr) ([]ma.Multiaddr, error) { if madns.Matches(raw) { - ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() mas, err := madns.Resolve(ctx, raw) if err != nil { return nil, err From 2a930b28a8d0a3739717d1e39d23f28a0147aa77 Mon Sep 17 00:00:00 2001 From: peekpi <894646171@qq.com> Date: Thu, 17 Jun 2021 16:46:46 +0800 Subject: [PATCH 2/2] [tracer] optimize CPU usage of trace_block RPC * use single Goroutines to deal trace task * drop trace task if request is canceld. --- hmy/tracer.go | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/hmy/tracer.go b/hmy/tracer.go index 9848ecf0e..8d9c508ca 100644 --- a/hmy/tracer.go +++ b/hmy/tracer.go @@ -342,10 +342,84 @@ func (hmy *Harmony) TraceChain(ctx context.Context, start, end *types.Block, con return sub, nil } +// same as TraceBlock, but only use 1 thread +func (hmy *Harmony) traceBlockNoThread(ctx context.Context, block *types.Block, config *TraceConfig) ([]*TxTraceResult, error) { + // Create the parent state database + if err := hmy.BlockChain.Engine().VerifyHeader(hmy.BlockChain, block.Header(), true); err != nil { + return nil, err + } + parent := hmy.BlockChain.GetBlock(block.ParentHash(), block.NumberU64()-1) + if parent == nil { + return nil, fmt.Errorf("parent %#x not found", block.ParentHash()) + } + reexec := defaultTraceReexec + if config != nil && config.Reexec != nil { + reexec = *config.Reexec + } + statedb, err := hmy.ComputeStateDB(parent, reexec) + if err != nil { + return nil, err + } + // Execute all the transaction contained within the block concurrently + var ( + hmySigner = types.MakeSigner(hmy.BlockChain.Config(), block.Number()) + ethSigner = types.NewEIP155Signer(hmy.BlockChain.Config().EthCompatibleChainID) + txs = block.Transactions() + results = make([]*TxTraceResult, len(txs)) + ) + + blockHash := block.Hash() + // Feed the transactions into the tracers and return + var failed error +traceLoop: + for i, tx := range txs { + signer := hmySigner + if tx.IsEthCompatible() { + signer = ethSigner + } + // Generate the next state snapshot fast without tracing + msg, _ := tx.AsMessage(signer) + + ethTx := tx.ConvertToEth() + statedb.Prepare(ethTx.Hash(), blockHash, i) + vmctx := core.NewEVMContext(msg, block.Header(), hmy.BlockChain, nil) + res, err := hmy.TraceTx(ctx, msg, vmctx, statedb, config) + if err != nil { + results[i] = &TxTraceResult{Error: err.Error()} + failed = err + break + } + results[i] = &TxTraceResult{Result: res} + // Finalize the state so any modifications are written to the trie + statedb.Finalise(true) + select { + case <-ctx.Done(): + failed = errors.New("trace task was canceled!") + break traceLoop + default: + } + } + + // If execution failed in between, abort + if failed != nil { + return nil, failed + } + return results, nil +} + // TraceBlock configures a new tracer according to the provided configuration, and // executes all the transactions contained within. The return value will be one item // per transaction, dependent on the requested tracer. func (hmy *Harmony) TraceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*TxTraceResult, error) { + select { + case <-ctx.Done(): + return nil, errors.New("canceled!") + default: + } + + if *config.Tracer == "ParityBlockTracer" { + return hmy.traceBlockNoThread(ctx, block, config) + } // Create the parent state database if err := hmy.BlockChain.Engine().VerifyHeader(hmy.BlockChain, block.Header(), true); err != nil { return nil, err