Use UArray instead of Set for builtin availability check#7736
Use UArray instead of Set for builtin availability check#7736
Conversation
The builtin availability check in `scriptCBORDecoder` was using `Set DefaultFun` for O(log n) membership, with a TODO suggesting `IntSet`. A `UArray DefaultFun Bool` is a better fit: since `DefaultFun` derives `Ix`, lookup is a true O(1) unboxed array index with no conversion at the lookup site. The array is built once per call via `runSTUArray`, folding over the `Set` through its `Foldable` instance (no intermediate list). The array covers all ~100 `DefaultFun` constructors.
|
Unclear this is an improvement. Try |
|
/benchmark validation-decode |
|
/benchmark validation-full |
|
Click here to check the status of your benchmark. |
|
Comparing benchmark results of 'validation-decode' on '0468c1c57d' (base) and 'f2742c451c' (PR) Results table
|
|
Click here to check the status of your benchmark. |
Unisay
left a comment
There was a problem hiding this comment.
Nice cleanup on the TODO.
Worth noting that the lookup is O(1) now, but the array itself gets rebuilt on every scriptCBORDecoder call. (ll, pv) ranges over a small finite set (four ledger languages times the handful of known protocol versions), so caching the array at module level costs almost nothing. Each decode then does a Map lookup instead of newArray plus a mapM_ over the Set.
Roughly:
availableBuiltinsArr
:: PlutusLedgerLanguage -> MajorProtocolVersion -> UArray DefaultFun Bool
availableBuiltinsArr =
let cache = Map.fromList
[((ll, pv), build ll pv) | ll <- [minBound .. maxBound], pv <- knownPVs]
build ll pv = runSTUArray $ do
arr <- newArray (minBound, maxBound) False
mapM_ (\f -> writeArray arr f True) (builtinsAvailableIn ll pv)
pure arr
in \ll pv -> Map.findWithDefault emptyArr (ll, pv) cacheMajorProtocolVersion doesn't have a meaningful Bounded instance, so knownPVs has to be listed by hand from Common/Versions.hs: alonzoPV, vasilPV, changPV, plominPV, vanRossemPV.
Whichever variant lands, it would be nice to see the win show up in plutus-benchmark:validation numbers before merging.
|
Comparing benchmark results of 'validation-full' on '0468c1c57d' (base) and 'f2742c451c' (PR) Results table
|
|
I'll defer this to @kwxm |
Summary
Addresses the
TODOinSerialisedScript.hs:202suggesting a better data structure for the builtin availability check inscriptCBORDecoder.Previously
checkBuiltindid an O(log n)Set.memberon aSet DefaultFun.DefaultFunalready derivesIx, so aUArray DefaultFun Boolgives a true O(1) unboxed array index with nofromEnum/hash at the lookup site (GHC'sIxinstance handles the offset).