-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: remove mempool.postCheck #158
Merged
jinsan-line
merged 10 commits into
Finschia:feat/perf
from
jinsan-line:remove-mempool-postcheck
Jan 6, 2021
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
6f25208
fix: error handling after check tx
jinsan-line a96d25f
fix: typo
jinsan-line 36acc18
chore: (mempool) remove postCheck and impl reserve
jinsan-line b40e1da
chore: fix tests
jinsan-line 9c1066e
chore: revise log (remove checkTx.Code)
jinsan-line e2145e4
chore: add `CONTRACT` for `mem.proxyAppConn.CheckTxAsync()`
jinsan-line 1b23f66
chore: revise numTxs, txsBytes for `ErrMempoolIsFull` in reserve()
jinsan-line 55990ec
chore: revise to remove redundant `isFull()`
jinsan-line 77f11db
fix: remove tx from cache when `app errors` or `failed to reserve`
jinsan-line 05a9349
Revert "chore: revise to remove redundant `isFull()`"
jinsan-line File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,10 @@ type CListMempool struct { | |
height int64 // the last block Update()'d to | ||
txsBytes int64 // total size of mempool, in bytes | ||
|
||
reserved int // the number of checking tx and it should be considered when checking mempool full | ||
reservedBytes int64 // size of checking tx and it should be considered when checking mempool full | ||
reservedMtx sync.Mutex | ||
|
||
// notify listeners (ie. consensus) when txs are available | ||
notifiedTxsAvailable bool | ||
txsAvailable chan struct{} // fires once for each height, when the mempool is not empty | ||
|
@@ -43,7 +47,6 @@ type CListMempool struct { | |
// CheckTx or ReapMaxBytesMaxGas(ReapMaxTxs) methods. | ||
updateMtx sync.RWMutex | ||
preCheck PreCheckFunc | ||
postCheck PostCheckFunc | ||
|
||
wal *auto.AutoFile // a log of mempool txs | ||
txs *clist.CList // concurrent linked-list of good txs | ||
|
@@ -118,12 +121,6 @@ func WithPreCheck(f PreCheckFunc) CListMempoolOption { | |
return func(mem *CListMempool) { mem.preCheck = f } | ||
} | ||
|
||
// WithPostCheck sets a filter for the mempool to reject a tx if f(tx) returns | ||
// false. This is ran after CheckTx. | ||
func WithPostCheck(f PostCheckFunc) CListMempoolOption { | ||
return func(mem *CListMempool) { mem.postCheck = f } | ||
} | ||
|
||
// WithMetrics sets the metrics. | ||
func WithMetrics(metrics *Metrics) CListMempoolOption { | ||
return func(mem *CListMempool) { mem.metrics = metrics } | ||
|
@@ -278,9 +275,19 @@ func (mem *CListMempool) CheckTx(tx types.Tx, cb func(*abci.Response), txInfo Tx | |
|
||
// NOTE: proxyAppConn may error if tx buffer is full | ||
if err := mem.proxyAppConn.Error(); err != nil { | ||
// remove from cache | ||
mem.cache.Remove(tx) | ||
return err | ||
} | ||
|
||
// reserve mempool that should be called just before calling `mem.proxyAppConn.CheckTxAsync()` | ||
if err := mem.reserve(int64(txSize)); err != nil { | ||
// remove from cache | ||
mem.cache.Remove(tx) | ||
return err | ||
} | ||
|
||
// CONTRACT: `app.CheckTxAsync()` should check whether `GasWanted` is valid (0 <= GasWanted <= block.masGas) | ||
reqRes := mem.proxyAppConn.CheckTxAsync(abci.RequestCheckTx{Tx: tx}) | ||
reqRes.SetCallback(mem.reqResCb(tx, txInfo.SenderID, txInfo.SenderP2PID, cb)) | ||
|
||
|
@@ -380,6 +387,35 @@ func (mem *CListMempool) isFull(txSize int) error { | |
return nil | ||
} | ||
|
||
func (mem *CListMempool) reserve(txSize int64) error { | ||
mem.reservedMtx.Lock() | ||
defer mem.reservedMtx.Unlock() | ||
|
||
var ( | ||
memSize = mem.Size() | ||
txsBytes = mem.TxsBytes() | ||
) | ||
|
||
if memSize+mem.reserved >= mem.config.Size || txSize+mem.reservedBytes+txsBytes > mem.config.MaxTxsBytes { | ||
return ErrMempoolIsFull{ | ||
memSize + mem.reserved, mem.config.Size, | ||
txsBytes + mem.reservedBytes, mem.config.MaxTxsBytes, | ||
} | ||
} | ||
|
||
mem.reserved++ | ||
mem.reservedBytes += txSize | ||
return nil | ||
} | ||
|
||
func (mem *CListMempool) releaseReserve(txSize int64) { | ||
mem.reservedMtx.Lock() | ||
defer mem.reservedMtx.Unlock() | ||
|
||
mem.reserved-- | ||
mem.reservedBytes -= txSize | ||
} | ||
|
||
// callback, which is called after the app checked the tx for the first time. | ||
// | ||
// The case where the app checks the tx for the second and subsequent times is | ||
|
@@ -392,20 +428,7 @@ func (mem *CListMempool) resCbFirstTime( | |
) { | ||
switch r := res.Value.(type) { | ||
case *abci.Response_CheckTx: | ||
var postCheckErr error | ||
if mem.postCheck != nil { | ||
postCheckErr = mem.postCheck(tx, r.CheckTx) | ||
} | ||
if (r.CheckTx.Code == abci.CodeTypeOK) && postCheckErr == nil { | ||
// Check mempool isn't full again to reduce the chance of exceeding the | ||
// limits. | ||
if err := mem.isFull(len(tx)); err != nil { | ||
// remove from cache (mempool might have a space later) | ||
mem.cache.Remove(tx) | ||
mem.logger.Error(err.Error()) | ||
return | ||
} | ||
|
||
if r.CheckTx.Code == abci.CodeTypeOK { | ||
memTx := &mempoolTx{ | ||
height: mem.height, | ||
gasWanted: r.CheckTx.GasWanted, | ||
|
@@ -423,11 +446,14 @@ func (mem *CListMempool) resCbFirstTime( | |
} else { | ||
// ignore bad transaction | ||
mem.logger.Info("Rejected bad transaction", | ||
"tx", txID(tx), "peerID", peerP2PID, "res", r, "err", postCheckErr) | ||
"tx", txID(tx), "peerID", peerP2PID, "res", r) | ||
mem.metrics.FailedTxs.Add(1) | ||
// remove from cache (it might be good later) | ||
mem.cache.Remove(tx) | ||
} | ||
|
||
// release `reserve` regardless it's OK or not (it might be good later) | ||
mem.releaseReserve(int64(len(tx))) | ||
default: | ||
// ignore other messages | ||
} | ||
|
@@ -448,15 +474,11 @@ func (mem *CListMempool) resCbRecheck(req *abci.Request, res *abci.Response) { | |
memTx.tx, | ||
tx)) | ||
} | ||
var postCheckErr error | ||
if mem.postCheck != nil { | ||
postCheckErr = mem.postCheck(tx, r.CheckTx) | ||
} | ||
if (r.CheckTx.Code == abci.CodeTypeOK) && postCheckErr == nil { | ||
if r.CheckTx.Code == abci.CodeTypeOK { | ||
// Good, nothing to do. | ||
} else { | ||
// Tx became invalidated due to newly committed block. | ||
mem.logger.Info("Tx is no longer valid", "tx", txID(tx), "res", r, "err", postCheckErr) | ||
mem.logger.Info("Tx is no longer valid", "tx", txID(tx), "res", r) | ||
// NOTE: we remove tx from the cache because it might be good later | ||
mem.removeTx(tx, mem.recheckCursor, true) | ||
} | ||
|
@@ -550,13 +572,12 @@ func (mem *CListMempool) ReapMaxTxs(max int) types.Txs { | |
return txs | ||
} | ||
|
||
// Lock() must be help by the caller during execution. | ||
// Lock() must be held by the caller during execution. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fix typo |
||
func (mem *CListMempool) Update( | ||
height int64, | ||
txs types.Txs, | ||
deliverTxResponses []*abci.ResponseDeliverTx, | ||
preCheck PreCheckFunc, | ||
postCheck PostCheckFunc, | ||
) error { | ||
// Set height | ||
mem.height = height | ||
|
@@ -565,9 +586,6 @@ func (mem *CListMempool) Update( | |
if preCheck != nil { | ||
mem.preCheck = preCheck | ||
} | ||
if postCheck != nil { | ||
mem.postCheck = postCheck | ||
} | ||
|
||
for i, tx := range txs { | ||
if deliverTxResponses[i].Code == abci.CodeTypeOK { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a
CONTRACT
comment.