Skip to content

Commit 9f7a6ef

Browse files
committed
Ensure that transaction tokens are unique in the mempool benchmarks
Data of type `Token` is what a mempool `TestBlock` transaction (`Tx`) consumes and produces. Previously, this token was a newtype around a `Word8`. There can only be around 256 unque `Word8` tokens, which means that its likely for this value to wrap around. In the current benchmark scenario, where we add linearly dependent transactions with only one input and output to a mempool, this wrap around was occurring and therefore the list of transaction that was being generated had many duplicates. The type of tokens is therefore changed to be a newtype around an `Int`, which won't wrap around (in a realistic benchmark). Abovementioned change exposed subtle performance effects on the mempool. Most of this can be attributed to the `Tx` type doubling as a `GenTxId`. The mempool keeps track of these identifiers in a set. Since there were only around 256 unique transactions, this set was rather small. Changing tokens to be `Int`s ensured that this set could grow much larger before becoming full, and that by itself has subtle effects on the performance of the mempool. Apart from changing the type of tokens, the mempool benchmark setup is reworked: * Transactions that are used as benchmark inputs are pre-generated and fully evaluated so that the generation work is not measured in the benchmarked function itself. * Instead of opening a mempool once and removing transactions after each benchmark run, a new mempool is opened in each benchmark run. Removing transactions proved to be prohibitively costly compared to the cost of opening a new mempool. * A new benchmark is added that measures just the mempool setup time. To obtain the cost of just adding the transactions without cost of opening the mempool, the time of this new benchmark can be manually subtracted from the full benchmark time.
1 parent 2201276 commit 9f7a6ef

File tree

2 files changed

+19
-16
lines changed

2 files changed

+19
-16
lines changed

ouroboros-consensus/bench/mempool-bench/Bench/Consensus/Mempool/TestBlock.hs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import Control.Monad.Trans.Except (except)
2828
import Data.Set (Set, (\\))
2929
import qualified Data.Set as Set
3030
import Data.TreeDiff (ToExpr)
31-
import Data.Word (Word8)
3231
import GHC.Generics (Generic)
3332
import NoThunks.Class (NoThunks)
3433
import qualified Ouroboros.Consensus.Block as Block
@@ -56,7 +55,7 @@ data Tx = Tx {
5655
deriving stock (Eq, Ord, Generic, Show)
5756
deriving anyclass (NoThunks, NFData)
5857

59-
newtype Token = Token { unToken :: Word8 }
58+
newtype Token = Token { unToken :: Int }
6059
deriving stock (Show, Eq, Ord, Generic)
6160
deriving anyclass (NoThunks, ToExpr, Serialise, NFData)
6261

@@ -81,7 +80,7 @@ sampleLedgerConfig = testBlockLedgerConfigFrom $
8180
-------------------------------------------------------------------------------}
8281

8382
data TestLedgerState = TestLedgerState {
84-
availableTokens :: Set Token
83+
availableTokens :: !(Set Token)
8584
}
8685
deriving stock (Generic, Eq, Show)
8786
deriving anyclass (NoThunks, ToExpr, Serialise)

ouroboros-consensus/bench/mempool-bench/Main.hs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import Bench.Consensus.Mempool
1111
import Bench.Consensus.Mempool.TestBlock (TestBlock)
1212
import qualified Bench.Consensus.Mempool.TestBlock as TestBlock
1313
import Control.Arrow (first)
14-
import Control.Monad (unless, void)
14+
import Control.DeepSeq
15+
import Control.Monad (unless)
1516
import qualified Control.Tracer as Tracer
1617
import Data.Aeson
1718
import qualified Data.ByteString.Lazy as BL
@@ -27,7 +28,7 @@ import qualified Test.Consensus.Mempool.Mocked as Mocked
2728
import Test.Consensus.Mempool.Mocked (MockedMempool)
2829
import Test.Tasty (withResource)
2930
import Test.Tasty.Bench (CsvPath (CsvPath), bench, benchIngredients,
30-
bgroup, nfIO)
31+
bgroup, whnfIO)
3132
import Test.Tasty.HUnit (testCase, (@?=))
3233
import Test.Tasty.Options (changeOption)
3334
import Test.Tasty.Runners (parseOptions, tryIngredients)
@@ -50,24 +51,27 @@ main = withStdTerminalHandles $ do
5051
where
5152
benchmarkJustAddingTransactions =
5253
bgroup "Just adding" $
53-
fmap benchAddNTxs [10_000, 1_000_000]
54+
fmap benchAddNTxs [10_000, 20_000]
5455
where
5556
benchAddNTxs n =
5657
withResource
57-
(let txs = mkNTryAddTxs n in fmap (, txs) (openMempoolWithCapacityFor txs))
58+
(pure $!! mkNTryAddTxs n)
5859
(\_ -> pure ())
59-
(\getAcquiredRes -> do
60-
let withAcquiredMempool act = do
61-
(mempool, txs) <- getAcquiredRes
62-
void $ act mempool txs
63-
-- TODO: consider adding a 'reset' command to the mempool to make sure its state is not tainted.
64-
Mocked.removeTxs mempool $ getCmdsTxIds txs
60+
(\getTxs -> do
6561
bgroup (show n <> " transactions") [
66-
bench "benchmark" $ nfIO $ withAcquiredMempool $ \mempool txs -> do
62+
bench "setup mempool" $ whnfIO $ do
63+
txs <- getTxs
64+
openMempoolWithCapacityFor txs
65+
, bench "setup mempool + benchmark" $ whnfIO $ do
66+
txs <- getTxs
67+
mempool <- openMempoolWithCapacityFor txs
6768
run mempool txs
68-
, testCase "test" $ withAcquiredMempool $ \mempool txs ->
69+
, testCase "test" $ do
70+
txs <- getTxs
71+
mempool <- openMempoolWithCapacityFor txs
6972
testAddTxs mempool txs
70-
, testCase "txs length" $ withAcquiredMempool $ \_mempool txs -> do
73+
, testCase "txs length" $ do
74+
txs <- getTxs
7175
length txs @?= n
7276
]
7377
)

0 commit comments

Comments
 (0)