-
Notifications
You must be signed in to change notification settings - Fork 502
Refined memory/cpu cost models for ValueData and UnValueData
#7500
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
Open
Unisay
wants to merge
6
commits into
master
Choose a base branch
from
yura/value-data-memory-models
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,226
−252
Conversation
This file contains hidden or 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
1bd6254 to
43bbe0a
Compare
Add new memory-analysis executable with modules for analyzing memory behavior of Plutus builtins. Includes plotting utilities, regression analysis, and experiment framework for deriving accurate memory models from empirical measurements.
Introduce DataNodeCount newtype that measures Data memory via lazy node traversal rather than serialization size. This provides more accurate memory accounting for UnValueData builtin which operates on the Data structure directly without serializing. The wrapper separates concerns: node counting logic here, cost coefficients in JSON models.
Add KnownTypeAst and builtin marshalling instances for DataNodeCount. This enables using the new memory model in builtin definitions while maintaining type safety through the universe system. Also includes minor refactoring (void instead of (() <$)) for clarity.
43bbe0a to
073fe97
Compare
Apply ValueTotalSize to ValueData and DataNodeCount to UnValueData, replacing plain Value/Data types. This enables accurate memory accounting: ValueData uses total serialized size, UnValueData uses node count for measuring input Data complexity.
Update ValueData and UnValueData benchmarks to use createOneTermBuiltinBenchWithWrapper with appropriate memory measurement wrappers (ValueTotalSize and DataNodeCount). This ensures benchmarks measure the same memory behavior as production builtins.
Replace constant memory costs with linear models derived from empirical measurements: - ValueData: memory = 38×size + 6 (was constant 1) - UnValueData: memory = 8×nodes + 0 (was constant 1) CPU: 290658×nodes + 1000 (was 43200×arg + 1000) The linear models better reflect actual memory behavior: ValueData scales with serialized size, UnValueData scales with node count. Benchmark data regenerated with new memory measurement approach.
073fe97 to
026e835
Compare
| @@ -0,0 +1,121 @@ | |||
| module PlutusBenchmark.RegressionInteger (integerBestFit) where | |||
Contributor
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 don't think we should implement our own linear regression algorithm when R is the domain standard for this.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Context
ValueDataandUnValueDatabuiltinsProblem Statement
The current cost models for
ValueDataandUnValueDatause constant memory costs of 1 unit, regardless of input size. This is inaccurate because:ValuetoData, memory should scale with serialized sizeDatatoValue, memory should scale with node count in the Data structureInaccurate memory models can lead to budget misestimation in smart contracts.
Solution Approach
This PR implements a comprehensive solution in 6 logical commits:
DataNodeCountnewtype for node-based memory trackingDataNodeCountinto the DefaultUni type systemValueTotalSize,DataNodeCount) to builtinsMemory Measurement Strategy
ValueTotalSizewrapper (already exists) - measures total serialized sizeDataNodeCountwrapper - performs lazy node traversal of Data structureThis approach separates concerns:
ExMemoryUsage.hs(slope applied per node/byte)Design Decisions
Why node count for UnValueData?
Data → Valueby traversing the Data tree structureCostRose) ensures accurate accountingWhy separate wrappers?
Changes
Memory Analysis Tooling
New executable:
plutus-benchmark:memory-analysisPlutusBenchmark.MemoryAnalysis: Main analysis frameworkPlutusBenchmark.MemoryAnalysis.Experiments: Memory behavior experimentsPlutusBenchmark.MemoryAnalysis.Generators: Test data generatorsPlutusBenchmark.Plotting: Chart generation utilitiesPlutusBenchmark.RegressionInteger: Regression with asymmetric lossThis tooling enabled empirical measurement of memory behavior to derive the coefficients used in the cost models.
Core Memory Tracking
plutus-core/src/PlutusCore/Evaluation/Machine/ExMemoryUsage.hs
DataNodeCountnewtype wrappingDataExMemoryUsageinstance usingcountNodesRoseScaledAllowAmbiguousTypes,BlockArguments,InstanceSigs,KindSignatures,ScopedTypeVariablesplutus-core/src/PlutusCore/Default/Universe.hs
KnownTypeAstinstance forDataNodeCountMakeKnownInandReadKnownIninstances for marshallingvoidinstead of(() <$)for clarityBuiltin Updates
plutus-core/src/PlutusCore/Default/Builtins.hs
ValueData: Changed signature fromValue -> DatatoValueTotalSize -> DataUnValueData: Changed signature fromData -> BuiltinResult ValuetoDataNodeCount -> BuiltinResult ValueBenchmark Alignment
plutus-core/cost-model/budgeting-bench/Benchmarks/Values.hs
valueDataBenchmarkto usecreateOneTermBuiltinBenchWithWrapperwithValueTotalSizeunValueDataBenchmarkto usecreateOneTermBuiltinBenchWithWrapperwithDataNodeCountCost Model Data
plutus-core/cost-model/data/builtinCostModel{A,B,C}.json
Updated memory models (all three variants updated identically):
Memory = 38 × size + 6 (was constant 1)
Memory = 8 × nodes + 0 (was constant 1)
CPU = 290658 × nodes + 1000 (updated from 43200 × arg + 1000)
plutus-core/cost-model/data/benching-conway.csv
Regenerated benchmark data (404 lines changed) with new memory measurement approach.
Impact
Budget Changes
Scripts using
ValueDataorUnValueDatawill see different memory budget consumption:Conformance Tests
Expect budget differences in conformance tests that use these builtins. The new costs are more accurate than the previous constant models.
4. Memory Analysis
The memory-analysis executable can reproduce the experiments:
This generates plots and regression analysis in
plutus-benchmark/memory-analysis/data/.5. Conformance Tests
cabal test plutus-conformanceExpect budget differences but correct behavior.
Notes for Reviewers
Commit Structure
The PR is organized as 6 atomic commits following dependency order:
Each commit is buildable and represents a logical unit of change.
The updated CPU models for
ValueDataandUnValueDatacould be previewed here.