diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index f42bae42ce..76da7e210d 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -101,6 +101,8 @@ var ( slotsGauge = metrics.NewRegisteredGauge("txpool/slots", nil) reheapTimer = metrics.NewRegisteredTimer("txpool/reheap", nil) + + txLifecycleTimer = metrics.NewRegisteredTimer("txpool/txfifecycle", nil) ) // BlockChain defines the minimal set of methods needed to back a tx pool with @@ -817,6 +819,7 @@ func (pool *LegacyPool) add(tx *types.Transaction, local bool) (replaced bool, e // New transaction is better, replace old one if old != nil { pool.all.Remove(old.Hash()) + pool.calculateTxsLifecycle(types.Transactions{old}, time.Now()) pool.priced.Removed(1) pendingReplaceMeter.Mark(1) } @@ -892,6 +895,7 @@ func (pool *LegacyPool) enqueueTx(hash common.Hash, tx *types.Transaction, local // Discard any previous transaction and mark this if old != nil { pool.all.Remove(old.Hash()) + pool.calculateTxsLifecycle(types.Transactions{old}, time.Now()) pool.priced.Removed(1) queuedReplaceMeter.Mark(1) } else { @@ -941,6 +945,7 @@ func (pool *LegacyPool) promoteTx(addr common.Address, hash common.Hash, tx *typ if !inserted { // An older transaction was better, discard this pool.all.Remove(hash) + pool.calculateTxsLifecycle(types.Transactions{tx}, time.Now()) pool.priced.Removed(1) pendingDiscardMeter.Mark(1) return false @@ -948,6 +953,7 @@ func (pool *LegacyPool) promoteTx(addr common.Address, hash common.Hash, tx *typ // Otherwise discard any previous transaction and mark this if old != nil { pool.all.Remove(old.Hash()) + pool.calculateTxsLifecycle(types.Transactions{old}, time.Now()) pool.priced.Removed(1) pendingReplaceMeter.Mark(1) } else { @@ -1156,6 +1162,7 @@ func (pool *LegacyPool) removeTx(hash common.Hash, outofbound bool, unreserve bo } // Remove it from the list of known transactions pool.all.Remove(hash) + pool.calculateTxsLifecycle(types.Transactions{tx}, time.Now()) if outofbound { pool.priced.Removed(1) } @@ -1499,6 +1506,7 @@ func (pool *LegacyPool) promoteExecutables(accounts []common.Address) []*types.T for _, tx := range forwards { hash := tx.Hash() pool.all.Remove(hash) + pool.calculateTxsLifecycle(types.Transactions{tx}, time.Now()) } log.Trace("Removed old queued transactions", "count", len(forwards)) @@ -1508,6 +1516,7 @@ func (pool *LegacyPool) promoteExecutables(accounts []common.Address) []*types.T for _, tx := range drops { hash := tx.Hash() pool.all.Remove(hash) + pool.calculateTxsLifecycle(types.Transactions{tx}, time.Now()) } log.Trace("Removed unpayable queued transactions", "count", len(drops)) queuedNofundsMeter.Mark(int64(len(drops))) @@ -1530,6 +1539,7 @@ func (pool *LegacyPool) promoteExecutables(accounts []common.Address) []*types.T for _, tx := range caps { hash := tx.Hash() pool.all.Remove(hash) + pool.calculateTxsLifecycle(types.Transactions{tx}, time.Now()) log.Trace("Removed cap-exceeding queued transaction", "hash", hash) } queuedRateLimitMeter.Mark(int64(len(caps))) @@ -1615,6 +1625,7 @@ func (pool *LegacyPool) truncatePending() { // Drop the transaction from the global pools too hash := tx.Hash() pool.all.Remove(hash) + pool.calculateTxsLifecycle(types.Transactions{tx}, time.Now()) // Update the account nonce to the dropped transaction pool.pendingNonces.setIfLower(offenders[i], tx.Nonce()) @@ -1642,6 +1653,7 @@ func (pool *LegacyPool) truncatePending() { // Drop the transaction from the global pools too hash := tx.Hash() pool.all.Remove(hash) + pool.calculateTxsLifecycle(types.Transactions{tx}, time.Now()) // Update the account nonce to the dropped transaction pool.pendingNonces.setIfLower(addr, tx.Nonce()) @@ -1722,6 +1734,7 @@ func (pool *LegacyPool) demoteUnexecutables() { for _, tx := range olds { hash := tx.Hash() pool.all.Remove(hash) + pool.calculateTxsLifecycle(types.Transactions{tx}, time.Now()) log.Trace("Removed old pending transaction", "hash", hash) } // Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later @@ -1731,6 +1744,7 @@ func (pool *LegacyPool) demoteUnexecutables() { hash := tx.Hash() log.Trace("Removed unpayable pending transaction", "hash", hash) pool.all.Remove(hash) + pool.calculateTxsLifecycle(types.Transactions{tx}, time.Now()) } pendingNofundsMeter.Mark(int64(len(drops))) @@ -1785,6 +1799,16 @@ func (pool *LegacyPool) ResumeReorgs() { } } +// calculateTxsLifecycle calculates the lifecycle of given txs +func (pool *LegacyPool) calculateTxsLifecycle(txs types.Transactions, t time.Time) { + for _, tx := range txs { + if tx.Time().Before(t) { + txLifecycle := t.Sub(tx.Time()) + txLifecycleTimer.Update(txLifecycle) + } + } +} + // addressByHeartbeat is an account address tagged with its last activity timestamp. type addressByHeartbeat struct { address common.Address