Skip to content

Commit 4fcf1a3

Browse files
authored
perf(builtins): optimize listToArray implementation and costing (#7468)
* perf(cost-model): optimize listToArray implementation and costing Improve listToArray builtin performance and costing precision: - Use Vector.fromListN instead of Vector.fromList to allocate exact array size upfront, avoiding incremental resizing overhead - Implement batched ExMemoryUsage for lists that processes spine in chunks of 100 elements for more efficient cost computation - Expand benchmark coverage to 1-5000 element lists for better cost model fitting across a wider range of input sizes * perf(cost-model): update listToArray CPU cost parameters Update listToArray cost model based on new benchmark results. The new implementation has lower base cost (intercept: 1000 vs 307802) but higher per-element cost (slope: 24619 vs 8496), reflecting the optimized algorithm that processes elements more efficiently with lower overhead. * docs(cost-models): add visualization pages for array builtins Add interactive cost model visualization pages for the three array builtin functions: ListToArray, LengthOfArray, and IndexArray. Each page displays benchmark data alongside fitted cost model predictions, following the established pattern for existing function visualizations. * test(conformance): update listToArray budget expectations Update expected CPU budgets for listToArray conformance tests to reflect the updated cost model parameters (lower intercept, higher slope). * refactor(core): add PlutusCore.Unroll module for static loop unrolling Extract Peano numbers, NatToPeano type family, and static unrolling utilities into a dedicated module. This consolidates type-level machinery for compile-time loop unrolling previously duplicated in StepCounter. Provides Drop class for statically unrolled list operations and UpwardsM class for statically unrolled effectful iteration. * refactor(cek): use PlutusCore.Unroll in StepCounter Remove duplicated Peano, NatToPeano, and UpwardsM definitions from StepCounter and import them from PlutusCore.Unroll instead. Reduces code duplication while maintaining identical runtime behavior. * perf(costing): use statically unrolled drop for list memoryUsage Replace splitAt with dropN in the ExMemoryUsage instance for lists. The dropN function uses compile-time instance resolution to unroll the drop operation, avoiding tuple and prefix list allocation that splitAt requires. * Update CPU slope in cost models A, B, and C to improve performance estimation - Changed the slope value from 24619 to 24838 in builtinCostModelA.json - Changed the slope value from 24619 to 24838 in builtinCostModelB.json - Changed the slope value from 24619 to 24838 in builtinCostModelC.json * test(conformance): update listToArray-02 budget expectation Adjust budget expectation for listToArray-02 test case to reflect the updated CPU slope in the cost model (286671 → 288642 cpu). * fix(cost-models): use Nop*o pattern for overhead calculation in JS Match R's models.R which uses Opaque (Nop*o) benchmarks for overhead calculation. The JS visualization was incorrectly using Nop*b pattern. * fix(cost-models): regenerate indexArray and lengthOfArray CPU costs These values were incorrect since commit 69cb3d9. Regenerated using generate-cost-model tool from current benching-conway.csv data.
1 parent 637c5be commit 4fcf1a3

File tree

24 files changed

+1792
-159
lines changed

24 files changed

+1792
-159
lines changed

doc/cost-models/index.html

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
<li><a href="unvaluedata/index.html">UnValueData</a></li>
1515
<li><a href="valuecontains/index.html">ValueContains</a></li>
1616
<li><a href="lookupcoin/index.html">LookupCoin</a></li>
17+
<li><a href="listtoarray/index.html">ListToArray</a></li>
18+
<li><a href="lengthofarray/index.html">LengthOfArray</a></li>
19+
<li><a href="indexarray/index.html">IndexArray</a></li>
1720
</ul>
1821
</nav>
1922

@@ -79,6 +82,30 @@ <h2>Available Visualizations</h2>
7982
(2D visualization: Value Size vs Time)
8083
</p>
8184
</li>
85+
86+
<li>
87+
<a href="listtoarray/index.html">ListToArray</a>
88+
<p class="description">
89+
Converts a Plutus list to an array representation.
90+
(2D visualization: List Size vs Time)
91+
</p>
92+
</li>
93+
94+
<li>
95+
<a href="lengthofarray/index.html">LengthOfArray</a>
96+
<p class="description">
97+
Returns the length of a Plutus array in O(1) time.
98+
(2D visualization: Array Size vs Time - constant cost)
99+
</p>
100+
</li>
101+
102+
<li>
103+
<a href="indexarray/index.html">IndexArray</a>
104+
<p class="description">
105+
Retrieves an element at a given index from a Plutus array in O(1) time.
106+
(2D visualization: Array Size vs Time - constant cost)
107+
</p>
108+
</li>
82109
</ul>
83110
</section>
84111

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>IndexArray - Plutus Cost Model Visualization</title>
7+
<link rel="stylesheet" href="../shared/styles.css">
8+
<script src="https://cdn.plot.ly/plotly-2.27.0.min.js"></script>
9+
</head>
10+
<body>
11+
<nav>
12+
<ul>
13+
<li><a href="../index.html">Home</a></li>
14+
<li><a href="../valuedata/index.html">ValueData</a></li>
15+
<li><a href="../unvaluedata/index.html">UnValueData</a></li>
16+
<li><a href="../valuecontains/index.html">ValueContains</a></li>
17+
<li><a href="../lookupcoin/index.html">LookupCoin</a></li>
18+
<li><a href="../listtoarray/index.html">ListToArray</a></li>
19+
<li><a href="../lengthofarray/index.html">LengthOfArray</a></li>
20+
<li><a href="../indexarray/index.html" class="active">IndexArray</a></li>
21+
</ul>
22+
</nav>
23+
24+
<div class="container">
25+
<h1>IndexArray Cost Model Visualization</h1>
26+
<p>
27+
Interactive visualization of benchmark data and fitted cost model for the <code>IndexArray</code> builtin function.
28+
This function retrieves an element at a given index from a Plutus array in O(1) time.
29+
</p>
30+
31+
<div class="controls" id="data-source-controls">
32+
<h3 id="data-source-toggle">Data Source Configuration</h3>
33+
<div class="controls-content">
34+
<div class="control-group-vertical">
35+
<label for="branch-name">Branch name:</label>
36+
<div class="branch-input-row">
37+
<input type="text" id="branch-name" placeholder="master">
38+
<button id="copy-link" title="Copy shareable link">Copy Link</button>
39+
</div>
40+
</div>
41+
<div class="control-group-vertical">
42+
<label for="csv-url">CSV file URL:</label>
43+
<input type="text" id="csv-url" style="width: 100%; font-family: monospace;">
44+
</div>
45+
<div class="control-group-vertical">
46+
<label for="json-url">JSON file URL:</label>
47+
<input type="text" id="json-url" style="width: 100%; font-family: monospace;">
48+
</div>
49+
<div class="control-group">
50+
<button id="reload-data">Load Data</button>
51+
</div>
52+
</div>
53+
</div>
54+
55+
<div class="controls" id="plot-controls">
56+
<h3 id="plot-controls-toggle">Plot Controls</h3>
57+
<div class="controls-content">
58+
<div class="control-group">
59+
<input type="checkbox" id="show-model" checked>
60+
<label for="show-model">Show model predictions</label>
61+
</div>
62+
<div class="control-group">
63+
<label for="y-axis-mode">Y-axis range:</label>
64+
<select id="y-axis-mode">
65+
<option value="zero">Start from 0</option>
66+
<option value="auto">Auto-scale from min</option>
67+
</select>
68+
</div>
69+
</div>
70+
</div>
71+
72+
<div class="plot-wrapper">
73+
<div id="plot-container">
74+
<div class="loading">Loading data and generating plot...</div>
75+
</div>
76+
77+
<div class="info-panel">
78+
<h3>Plot Information</h3>
79+
80+
<div class="info-section">
81+
<dl>
82+
<dt>X-axis:</dt>
83+
<dd id="info-x-axis">Array Size</dd>
84+
85+
<dt>Y-axis:</dt>
86+
<dd id="info-y-axis">Time (nanoseconds)</dd>
87+
88+
<dt>Description:</dt>
89+
<dd id="info-description">Each point represents one benchmark run (constant time regardless of array size or index)</dd>
90+
</dl>
91+
</div>
92+
93+
<div class="info-section">
94+
<dt>Cost Model Type:</dt>
95+
<dd id="info-model-type">Loading...</dd>
96+
97+
<dt>Model Formula (net):</dt>
98+
<dd class="formula" id="info-model-formula">Loading...</dd>
99+
100+
<dt>Overhead:</dt>
101+
<dd id="info-overhead">Loading...</dd>
102+
</div>
103+
104+
<div class="info-section">
105+
<dl>
106+
<dt>Data points:</dt>
107+
<dd id="info-data-points">-</dd>
108+
109+
<dt>Array Size range:</dt>
110+
<dd id="info-x-range">-</dd>
111+
112+
<dt>Time range:</dt>
113+
<dd id="info-time-range">-</dd>
114+
</dl>
115+
</div>
116+
117+
<div class="info-section">
118+
<dt>Data sources:</dt>
119+
<dd><a href="https://github.com/IntersectMBO/plutus/blob/master/plutus-core/cost-model/data/benching-conway.csv" target="_blank">benching-conway.csv</a></dd>
120+
<dd><a href="https://github.com/IntersectMBO/plutus/blob/master/plutus-core/cost-model/data/builtinCostModelC.json" target="_blank">builtinCostModelC.json</a></dd>
121+
</div>
122+
</div>
123+
</div>
124+
</div>
125+
126+
<footer>
127+
<p>Plutus Cost Model Visualization | <a href="https://github.com/IntersectMBO/plutus" target="_blank">Plutus Repository</a></p>
128+
</footer>
129+
130+
<script src="../shared/utils.js"></script>
131+
<script src="plot.js"></script>
132+
</body>
133+
</html>

0 commit comments

Comments
 (0)