Skip to content

Commit 5f9269b

Browse files
committed
Add support for unique keys, WIP benchmarking
1 parent fe88295 commit 5f9269b

File tree

2 files changed

+62
-16
lines changed

2 files changed

+62
-16
lines changed

plutus-core/cost-model/budgeting-bench/Benchmarks/Values.hs

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,34 @@ import PlutusCore (DefaultFun (InsertCoin, LookupCoin, UnValueData, ValueContain
1010
import PlutusCore.Value (Value)
1111
import PlutusCore.Value qualified as Value
1212

13-
import Control.Monad.State (State)
13+
import Control.Monad.Trans.Class (lift)
14+
import Control.Monad.Trans.State.Strict (State, StateT, evalState, gets, modify)
1415
import Criterion.Main (Benchmark)
1516
import Data.ByteString (ByteString)
16-
import System.Random.Stateful (StageGenM, StatefulGen, StdGen, UniformRange (uniformRM),
17-
runStateGen_, uniformByteStringM)
17+
import Data.ByteString qualified as BS
18+
import Data.Text qualified as Text
19+
import Data.Text.Encoding (encodeUtf8)
20+
import Data.Word (Word8)
21+
import System.Random.Stateful (StateGenM, StatefulGen, StdGen, UniformRange (uniformRM),
22+
runStateGenT_, uniformByteStringM)
1823

1924
makeBenchmarks :: StdGen -> [Benchmark]
2025
makeBenchmarks gen =
2126
[ benchInsertCoin gen
2227
-- , benchUnionValue gen
2328
]
2429

25-
type PolicyId = ByteString
26-
type TokenName = ByteString
27-
type Amount = Integer
30+
newtype PolicyId = PolicyId ByteString
31+
newtype TokenName = TokenName ByteString
32+
newtype Amount = Amount Integer
33+
type Counter = Integer
34+
35+
data GenState = GenState
36+
{ policyIdCounter :: Counter
37+
, tokenNameCounter :: Counter
38+
}
39+
40+
type BenchState = StateT StdGen (State GenState)
2841

2942
-- | An insertCoin benchmark is a concrete set of arguments we apply to the
3043
-- InsertCoin builtin function to measure its runtime cost.
@@ -35,30 +48,62 @@ data InsertCoinBenchmark = InsertCoinBenchmark
3548
, icValue :: Value
3649
}
3750

38-
icToTuple :: InsertCoinBenchmark -> (PolicyId, TokenName, Amount, Value)
39-
icToTuple (InsertCoinBenchmark p t a v) = (p, t, a, v)
51+
icToRawTuple :: InsertCoinBenchmark -> (ByteString, ByteString, Integer, Value)
52+
icToRawTuple (InsertCoinBenchmark (PolicyId p) (TokenName t) (Amount a) v) = (p, t, a, v)
4053

4154
benchInsertCoin :: StdGen -> Benchmark
4255
benchInsertCoin gen =
4356
createFourTermBuiltinBenchElementwiseWithWrappers
4457
(id, id, id, id) -- TODO: use proper wrappers
4558
InsertCoin
4659
[]
47-
(icToTuple <$> insertCoinBenchGen gen)
60+
(icToRawTuple <$> insertCoinBenchGen gen)
4861

4962
-- | Generate a set of benchmarks for the InsertCoin builtin function.
5063
-- It includes the following scenarios:
5164
-- 1. Inserting into an empty Value.
52-
-- 2. Inserting a new TokenName into an existing PolicyId.
53-
-- 3. Inserting into an existing TokenName.
65+
-- 2. Inserting a new TokenName into an existing PolicyId. Randomly extracting a PolicyId from the Value.
66+
-- 3. Inserting into an existing TokenName. Randomly extracting a (PolicyId, TokenName) pair from the Value.
5467
-- 4. Inserting a new PolicyId.
55-
-- 5. Deleting a TokenName by inserting a 0 amount.
56-
-- 6. Deleting a PolicyId by inserting a 0 amount into its last TokenName.
68+
-- 5. Deleting a TokenName by inserting a 0 amount. Randomly extracting a (PolicyId, TokenName) pair from the Value.
69+
-- 6. Deleting a PolicyId by inserting a 0 amount into its last TokenName. Should generate a Value with multiple such PolicyIds, and randomly picking which PolicyId to delete.
5770
-- We're interested in the worst case performance, so we'll use the largest key values possible.
71+
-- Each one of the cases should be applied to monotonically increasing sizes of the Value.
72+
-- We should also run randomized benchmarks, where we insert random values into random Values.
5873
insertCoinBenchGen
5974
:: StdGen
6075
-> [InsertCoinBenchmark]
61-
insertCoinBenchGen g = undefined
76+
insertCoinBenchGen g = flip evalState (GenState 0 0) $ runStateGenT_ g $ \gen -> do
77+
policyId <- newPolicyId gen
78+
tokenName <- newTokenName gen
79+
amount <- uniformAmount gen
80+
let emptyValueBench = InsertCoinBenchmark policyId tokenName amount Value.empty
81+
pure [emptyValueBench]
82+
83+
-- | Generate a unique PolicyId on a uniform distribution. Note that the size of the
84+
-- generated bytestring is going to be larger than Value.maxKeyLen, because we
85+
-- append a counter integer to ensure uniqueness. This is acceptable for benchmarking
86+
-- purposes, as we're interested in the worst-case performance.
87+
newPolicyId :: StateGenM StdGen -> BenchState PolicyId
88+
newPolicyId gen = do
89+
bs <- uniformByteStringM Value.maxKeyLen gen
90+
c <- lift $ gets policyIdCounter
91+
let newbs = BS.append bs (encodeUtf8 . Text.pack . show $ c)
92+
lift $ modify $ \s -> s { policyIdCounter = c + 1 }
93+
pure $ PolicyId newbs
94+
95+
-- | Generate a unique TokenName on a uniform distribution. Note that the size of the
96+
-- generated bytestring is going to be larger than Value.maxKeyLen, because we
97+
-- append a counter integer to ensure uniqueness. This is acceptable for benchmarking
98+
-- purposes, as we're interested in the worst-case performance.
99+
newTokenName :: StateGenM StdGen -> BenchState TokenName
100+
newTokenName gen = do
101+
bs <- uniformByteStringM Value.maxKeyLen gen
102+
c <- lift $ gets tokenNameCounter
103+
let newbs = BS.append bs (encodeUtf8 . Text.pack . show $ c)
104+
lift $ modify $ \s -> s { tokenNameCounter = c + 1 }
105+
pure $ TokenName newbs
62106

63-
uniformByteString :: StdGen -> ByteString
64-
uniformByteString gen = uniformByteString Value.maxKeyLen gen
107+
uniformAmount :: StateGenM StdGen -> BenchState Amount
108+
uniformAmount gen =
109+
Amount <$> uniformRM (0, 100) gen

plutus-core/plutus-core.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,7 @@ executable cost-model-budgeting-bench
959959
, random
960960
, text
961961
, time
962+
, transformers
962963
, vector
963964

964965
-- This reads CSV data generated by cost-model-budgeting-bench, uses R to build

0 commit comments

Comments
 (0)