Skip to content

[Builtins] Add constant casing for builtin unit and pair#7221

Merged
SeungheonOh merged 15 commits intomasterfrom
sho/6602-unitpair
Sep 2, 2025
Merged

[Builtins] Add constant casing for builtin unit and pair#7221
SeungheonOh merged 15 commits intomasterfrom
sho/6602-unitpair

Conversation

@SeungheonOh
Copy link
Collaborator

@SeungheonOh SeungheonOh commented Jul 17, 2025

part of #6602
closes #7220

Casing on unit expects exactly one branch with no arguments, which will get picked everytime.
Casing on pair also expects exactly one branch with two arguments, for each parts of the pair.

@github-actions
Copy link
Contributor

github-actions bot commented Jul 17, 2025

PR Preview Action v1.6.2

🚀 View preview at
https://IntersectMBO.github.io/plutus/pr-preview/pr-7221/

Built to branch gh-pages at 2025-09-02 06:06 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@SeungheonOh SeungheonOh self-assigned this Jul 17, 2025
@SeungheonOh
Copy link
Collaborator Author

/benchmark lists

@github-actions
Copy link
Contributor

Click here to check the status of your benchmark.

@github-actions
Copy link
Contributor

Comparing benchmark results of 'lists' on '2a8dc3e39b' (base) and '77ec468270' (PR)

Results table
Script 2a8dc3e 77ec468 Change
sort/ghcSort/50 136.2 μs 169.2 μs +24.2%
sort/ghcSort/100 313.2 μs 390.8 μs +24.8%
sort/ghcSort/150 536.6 μs 675.1 μs +25.8%
sort/ghcSort/200 720.7 μs 911.0 μs +26.4%
sort/ghcSort/250 902.3 μs 1.143 ms +26.7%
sort/ghcSort/300 1.231 ms 1.551 ms +26.0%
sort/insertionSort/50 441.9 μs 574.4 μs +30.0%
sort/insertionSort/100 1.759 ms 2.303 ms +30.9%
sort/insertionSort/150 3.957 ms 5.246 ms +32.6%
sort/insertionSort/200 7.079 ms 9.246 ms +30.6%
sort/insertionSort/250 11.09 ms 14.47 ms +30.5%
sort/insertionSort/300 16.05 ms 21.35 ms +33.0%
sort/mergeSort/50 420.5 μs 541.3 μs +28.7%
sort/mergeSort/100 965.7 μs 1.247 ms +29.1%
sort/mergeSort/150 1.566 ms 2.017 ms +28.8%
sort/mergeSort/200 2.195 ms 2.826 ms +28.7%
sort/mergeSort/250 2.882 ms 3.710 ms +28.7%
sort/mergeSort/300 3.510 ms 4.529 ms +29.0%
sort/quickSort/50 1.044 ms 1.304 ms +24.9%
sort/quickSort/100 4.415 ms 5.425 ms +22.9%
sort/quickSort/150 9.933 ms 12.23 ms +23.1%
sort/quickSort/200 17.62 ms 21.64 ms +22.8%
sort/quickSort/250 27.79 ms 34.03 ms +22.5%
sort/quickSort/300 40.26 ms 49.22 ms +22.3%
sum/compiled-from-Haskell/sum-right-builtin/100 44.17 μs 49.47 μs +12.0%
sum/compiled-from-Haskell/sum-right-builtin/500 232.8 μs 259.8 μs +11.6%
sum/compiled-from-Haskell/sum-right-builtin/1000 500.4 μs 552.3 μs +10.4%
sum/compiled-from-Haskell/sum-right-builtin/2500 1.643 ms 1.773 ms +7.9%
sum/compiled-from-Haskell/sum-right-builtin/5000 3.961 ms 4.198 ms +6.0%
sum/compiled-from-Haskell/sum-right-Scott/100 43.74 μs 49.27 μs +12.6%
sum/compiled-from-Haskell/sum-right-Scott/500 234.3 μs 262.4 μs +12.0%
sum/compiled-from-Haskell/sum-right-Scott/1000 517.4 μs 566.6 μs +9.5%
sum/compiled-from-Haskell/sum-right-Scott/2500 1.838 ms 1.950 ms +6.1%
sum/compiled-from-Haskell/sum-right-Scott/5000 4.264 ms 4.480 ms +5.1%
sum/compiled-from-Haskell/sum-right-data/100 187.0 μs 216.6 μs +15.8%
sum/compiled-from-Haskell/sum-right-data/500 1.030 ms 1.181 ms +14.7%
sum/compiled-from-Haskell/sum-right-data/1000 2.422 ms 2.731 ms +12.8%
sum/compiled-from-Haskell/sum-right-data/2500 6.821 ms 7.558 ms +10.8%
sum/compiled-from-Haskell/sum-right-data/5000 14.73 ms 16.20 ms +10.0%
sum/compiled-from-Haskell/sum-left-builtin/100 43.91 μs 53.33 μs +21.5%
sum/compiled-from-Haskell/sum-left-builtin/500 231.2 μs 278.9 μs +20.6%
sum/compiled-from-Haskell/sum-left-builtin/1000 497.9 μs 591.0 μs +18.7%
sum/compiled-from-Haskell/sum-left-builtin/2500 1.601 ms 1.826 ms +14.1%
sum/compiled-from-Haskell/sum-left-builtin/5000 3.889 ms 4.330 ms +11.3%
sum/compiled-from-Haskell/sum-left-Scott/100 42.58 μs 53.07 μs +24.6%
sum/compiled-from-Haskell/sum-left-Scott/500 230.4 μs 279.6 μs +21.4%
sum/compiled-from-Haskell/sum-left-Scott/1000 501.7 μs 600.0 μs +19.6%
sum/compiled-from-Haskell/sum-left-Scott/2500 1.742 ms 1.979 ms +13.6%
sum/compiled-from-Haskell/sum-left-Scott/5000 4.131 ms 4.612 ms +11.6%
sum/compiled-from-Haskell/sum-left-data/100 188.1 μs 224.2 μs +19.2%
sum/compiled-from-Haskell/sum-left-data/500 1.043 ms 1.223 ms +17.3%
sum/compiled-from-Haskell/sum-left-data/1000 2.427 ms 2.788 ms +14.9%
sum/compiled-from-Haskell/sum-left-data/2500 6.905 ms 7.676 ms +11.2%
sum/compiled-from-Haskell/sum-left-data/5000 14.76 ms 16.51 ms +11.9%
sum/hand-written-PLC/sum-right-builtin/100 75.70 μs 97.84 μs +29.2%
sum/hand-written-PLC/sum-right-builtin/500 392.5 μs 496.3 μs +26.4%
sum/hand-written-PLC/sum-right-builtin/1000 817.2 μs 1.023 ms +25.2%
sum/hand-written-PLC/sum-right-builtin/2500 2.314 ms 2.817 ms +21.7%
sum/hand-written-PLC/sum-right-builtin/5000 4.866 ms 5.899 ms +21.2%
sum/hand-written-PLC/sum-right-Scott/100 36.62 μs 35.96 μs -1.8%
sum/hand-written-PLC/sum-right-Scott/500 197.9 μs 193.5 μs -2.2%
sum/hand-written-PLC/sum-right-Scott/1000 443.2 μs 441.7 μs -0.3%
sum/hand-written-PLC/sum-right-Scott/2500 1.579 ms 1.562 ms -1.1%
sum/hand-written-PLC/sum-right-Scott/5000 4.551 ms 4.518 ms -0.7%
sum/hand-written-PLC/sum-left-builtin/100 80.13 μs 103.9 μs +29.7%
sum/hand-written-PLC/sum-left-builtin/500 393.6 μs 508.0 μs +29.1%
sum/hand-written-PLC/sum-left-builtin/1000 782.4 μs 1.015 ms +29.7%
sum/hand-written-PLC/sum-left-builtin/2500 1.934 ms 2.522 ms +30.4%
sum/hand-written-PLC/sum-left-builtin/5000 3.855 ms 5.022 ms +30.3%
sum/hand-written-PLC/sum-left-Scott/100 39.57 μs 40.03 μs +1.2%
sum/hand-written-PLC/sum-left-Scott/500 212.7 μs 219.1 μs +3.0%
sum/hand-written-PLC/sum-left-Scott/1000 480.2 μs 490.3 μs +2.1%
sum/hand-written-PLC/sum-left-Scott/2500 1.770 ms 1.775 ms +0.3%
sum/hand-written-PLC/sum-left-Scott/5000 4.565 ms 4.552 ms -0.3%
2a8dc3e 77ec468 Change
TOTAL 262.9 ms 315.1 ms +19.9%

@SeungheonOh
Copy link
Collaborator Author

I made changes to plugin so that it will use constant casing for FstPair, SndPair, and ChooseUnit. This have improved execution budget around 10% to 20%; however, introduced rather impressive ~30% slowdown.

(fstPair {integer} {b} tup)
(sndPair {integer} {b} tup))
(case integer tup [(\(l : integer) (r : b) -> l)])
(case b tup [(\(l : integer) (r : b) -> r)]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's of course the issue that we want to only case on tup once, i.e. we currently generate sub-optimal code.

Not for this PR though, should be addressed in a follow-up.

@@ -1 +1,2 @@
\(p : pair integer integer) -> fstPair {integer} {integer} p No newline at end of file
\(p : pair integer integer) ->
case integer p [(\(l : integer) (r : integer) -> l)] No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I guess it's not entirely unreasonable that calling a builtin once can be faster than evaluating a Case node, two function applications and a variable lookup.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Especially given that a builtin does something very similar to what a case does, except with less noise and with better optimizations.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, and cost model doesn't reflect this correctly. The cost might only even out when we compare taking both values from pair, running FstPair and SndPair both.

I don't think we can replace FstPair and SndPair

@SeungheonOh
Copy link
Collaborator Author

/benchmark lists

@github-actions
Copy link
Contributor

Click here to check the status of your benchmark.

@github-actions
Copy link
Contributor

Comparing benchmark results of 'lists' on '2a8dc3e39b' (base) and '77ec468270' (PR)

Results table
Script 2a8dc3e 77ec468 Change
sort/ghcSort/50 134.8 μs 138.6 μs +2.8%
sort/ghcSort/100 309.4 μs 316.2 μs +2.2%
sort/ghcSort/150 532.6 μs 544.5 μs +2.2%
sort/ghcSort/200 718.8 μs 729.1 μs +1.4%
sort/ghcSort/250 901.0 μs 920.0 μs +2.1%
sort/ghcSort/300 1.224 ms 1.248 ms +2.0%
sort/insertionSort/50 438.4 μs 432.2 μs -1.4%
sort/insertionSort/100 1.748 ms 1.720 ms -1.6%
sort/insertionSort/150 3.948 ms 3.886 ms -1.6%
sort/insertionSort/200 7.007 ms 6.924 ms -1.2%
sort/insertionSort/250 11.03 ms 10.85 ms -1.6%
sort/insertionSort/300 16.04 ms 15.70 ms -2.1%
sort/mergeSort/50 417.9 μs 427.3 μs +2.2%
sort/mergeSort/100 958.9 μs 979.1 μs +2.1%
sort/mergeSort/150 1.551 ms 1.586 ms +2.3%
sort/mergeSort/200 2.183 ms 2.229 ms +2.1%
sort/mergeSort/250 2.867 ms 2.928 ms +2.1%
sort/mergeSort/300 3.494 ms 3.563 ms +2.0%
sort/quickSort/50 1.041 ms 1.039 ms -0.2%
sort/quickSort/100 4.390 ms 4.391 ms +0.0%
sort/quickSort/150 9.876 ms 9.853 ms -0.2%
sort/quickSort/200 17.51 ms 17.43 ms -0.5%
sort/quickSort/250 27.62 ms 27.47 ms -0.5%
sort/quickSort/300 40.12 ms 39.74 ms -0.9%
sum/compiled-from-Haskell/sum-right-builtin/100 43.50 μs 44.24 μs +1.7%
sum/compiled-from-Haskell/sum-right-builtin/500 230.1 μs 233.5 μs +1.5%
sum/compiled-from-Haskell/sum-right-builtin/1000 496.4 μs 501.3 μs +1.0%
sum/compiled-from-Haskell/sum-right-builtin/2500 1.632 ms 1.651 ms +1.2%
sum/compiled-from-Haskell/sum-right-builtin/5000 3.935 ms 3.933 ms -0.1%
sum/compiled-from-Haskell/sum-right-Scott/100 43.47 μs 44.48 μs +2.3%
sum/compiled-from-Haskell/sum-right-Scott/500 232.7 μs 234.6 μs +0.8%
sum/compiled-from-Haskell/sum-right-Scott/1000 513.3 μs 514.2 μs +0.2%
sum/compiled-from-Haskell/sum-right-Scott/2500 1.825 ms 1.828 ms +0.2%
sum/compiled-from-Haskell/sum-right-Scott/5000 4.238 ms 4.219 ms -0.4%
sum/compiled-from-Haskell/sum-right-data/100 186.8 μs 176.4 μs -5.6%
sum/compiled-from-Haskell/sum-right-data/500 1.032 ms 980.2 μs -5.0%
sum/compiled-from-Haskell/sum-right-data/1000 2.404 ms 2.341 ms -2.6%
sum/compiled-from-Haskell/sum-right-data/2500 6.802 ms 6.557 ms -3.6%
sum/compiled-from-Haskell/sum-right-data/5000 14.61 ms 14.17 ms -3.0%
sum/compiled-from-Haskell/sum-left-builtin/100 43.46 μs 44.05 μs +1.4%
sum/compiled-from-Haskell/sum-left-builtin/500 229.2 μs 232.6 μs +1.5%
sum/compiled-from-Haskell/sum-left-builtin/1000 495.2 μs 497.0 μs +0.4%
sum/compiled-from-Haskell/sum-left-builtin/2500 1.586 ms 1.592 ms +0.4%
sum/compiled-from-Haskell/sum-left-builtin/5000 3.859 ms 3.862 ms +0.1%
sum/compiled-from-Haskell/sum-left-Scott/100 42.48 μs 43.97 μs +3.5%
sum/compiled-from-Haskell/sum-left-Scott/500 229.0 μs 234.5 μs +2.4%
sum/compiled-from-Haskell/sum-left-Scott/1000 498.2 μs 510.8 μs +2.5%
sum/compiled-from-Haskell/sum-left-Scott/2500 1.728 ms 1.760 ms +1.9%
sum/compiled-from-Haskell/sum-left-Scott/5000 4.114 ms 4.158 ms +1.1%
sum/compiled-from-Haskell/sum-left-data/100 187.3 μs 181.0 μs -3.4%
sum/compiled-from-Haskell/sum-left-data/500 1.038 ms 1.007 ms -3.0%
sum/compiled-from-Haskell/sum-left-data/1000 2.412 ms 2.367 ms -1.9%
sum/compiled-from-Haskell/sum-left-data/2500 6.877 ms 6.598 ms -4.1%
sum/compiled-from-Haskell/sum-left-data/5000 14.69 ms 14.36 ms -2.2%
sum/hand-written-PLC/sum-right-builtin/100 75.50 μs 77.31 μs +2.4%
sum/hand-written-PLC/sum-right-builtin/500 390.4 μs 395.7 μs +1.4%
sum/hand-written-PLC/sum-right-builtin/1000 807.2 μs 818.1 μs +1.4%
sum/hand-written-PLC/sum-right-builtin/2500 2.290 ms 2.313 ms +1.0%
sum/hand-written-PLC/sum-right-builtin/5000 4.820 ms 4.871 ms +1.1%
sum/hand-written-PLC/sum-right-Scott/100 36.19 μs 36.71 μs +1.4%
sum/hand-written-PLC/sum-right-Scott/500 195.7 μs 195.3 μs -0.2%
sum/hand-written-PLC/sum-right-Scott/1000 440.3 μs 443.6 μs +0.7%
sum/hand-written-PLC/sum-right-Scott/2500 1.565 ms 1.578 ms +0.8%
sum/hand-written-PLC/sum-right-Scott/5000 4.533 ms 4.539 ms +0.1%
sum/hand-written-PLC/sum-left-builtin/100 79.68 μs 81.25 μs +2.0%
sum/hand-written-PLC/sum-left-builtin/500 391.1 μs 404.0 μs +3.3%
sum/hand-written-PLC/sum-left-builtin/1000 777.4 μs 794.3 μs +2.2%
sum/hand-written-PLC/sum-left-builtin/2500 1.923 ms 1.980 ms +3.0%
sum/hand-written-PLC/sum-left-builtin/5000 3.835 ms 3.940 ms +2.7%
sum/hand-written-PLC/sum-left-Scott/100 39.14 μs 40.54 μs +3.6%
sum/hand-written-PLC/sum-left-Scott/500 214.0 μs 219.2 μs +2.4%
sum/hand-written-PLC/sum-left-Scott/1000 481.3 μs 491.9 μs +2.2%
sum/hand-written-PLC/sum-left-Scott/2500 1.762 ms 1.786 ms +1.4%
sum/hand-written-PLC/sum-left-Scott/5000 4.536 ms 4.581 ms +1.0%
2a8dc3e 77ec468 Change
TOTAL 261.5 ms 259.5 ms -0.8%

@SeungheonOh
Copy link
Collaborator Author

Okay, we just got trolled by benchmark machine

@IntersectMBO IntersectMBO deleted a comment from github-actions bot Jul 17, 2025
@IntersectMBO IntersectMBO deleted a comment from github-actions bot Jul 17, 2025
@IntersectMBO IntersectMBO deleted a comment from github-actions bot Jul 17, 2025
@IntersectMBO IntersectMBO deleted a comment from github-actions bot Jul 17, 2025
@IntersectMBO IntersectMBO deleted a comment from github-actions bot Jul 17, 2025
@SeungheonOh
Copy link
Collaborator Author

/benchmark casing

@github-actions
Copy link
Contributor

Comparing benchmark results of 'casing' on '2a8dc3e39b' (base) and 'befce2611e' (PR)

Results table
Script 2a8dc3e befce26 Change
2a8dc3e befce26 Change
TOTAL 0.000 ps 0.000 ps -

@github-actions
Copy link
Contributor

Click here to check the status of your benchmark.

@SeungheonOh SeungheonOh changed the title Add constant casing for builtin unit and pair [Builtins] Add constant casing for builtin unit and pair Jul 18, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Aug 21, 2025

Execution Budget Golden Diff

be38083 (master) vs d4bdf6e

output

plutus-benchmark/cardano-loans/test/9.6/main.eval.golden

Metric Old New Δ%
CPU 121_424_595 110_908_889 -8.66%
Memory 621_882 621_150 -0.12%
Term Size 8_054 7_446 -7.55%
Flat Size 9_189 8_702 -5.30%

plutus-benchmark/coop/test/9.6/authMpBurning.eval.golden

Metric Old New Δ%
CPU 263_521_586 160_613_384 -39.05%
Memory 1_021_910 799_466 -21.77%
Term Size 1_720 1_473 -14.36%
Flat Size 5_582 5_393 -3.39%

plutus-benchmark/coop/test/9.6/authMpMinting.eval.golden

Metric Old New Δ%
CPU 568_485_855 369_713_157 -34.97%
Memory 2_315_312 1_849_456 -20.12%
Term Size 1_720 1_473 -14.36%
Flat Size 6_979 6_790 -2.71%

plutus-benchmark/coop/test/9.6/certMpBurning.eval.golden

Metric Old New Δ%
CPU 1_990_939_611 1_842_342_144 -7.46%
Memory 11_112_742 10_767_218 -3.11%
Term Size 3_433 3_160 -7.95%
Flat Size 8_250 8_041 -2.53%

plutus-benchmark/coop/test/9.6/certMpMinting.eval.golden

Metric Old New Δ%
CPU 603_286_060 400_086_379 -33.68%
Memory 2_503_588 2_025_456 -19.10%
Term Size 3_433 3_160 -7.95%
Flat Size 8_773 8_564 -2.38%

plutus-benchmark/coop/test/9.6/fsMpBurning.eval.golden

Metric Old New Δ%
CPU 313_686_064 221_694_924 -29.33%
Memory 1_359_255 1_160_575 -14.62%
Term Size 3_883 3_571 -8.04%
Flat Size 7_645 7_405 -3.14%

plutus-benchmark/coop/test/9.6/fsMpMinting.eval.golden

Metric Old New Δ%
CPU 747_548_650 568_150_641 -24.00%
Memory 3_472_715 3_047_567 -12.24%
Term Size 3_883 3_571 -8.04%
Flat Size 9_463 9_223 -2.54%

plutus-benchmark/coop/test/9.6/mustBurnOwnSingleton.eval.golden

Metric Old New Δ%
CPU 181_130_390 114_113_035 -37.00%
Memory 716_465 579_805 -19.07%
Term Size 1_508 1_274 -15.52%
Flat Size 4_012 3_833 -4.46%

plutus-benchmark/linear-vesting/test/9.6/main.eval.golden

Metric Old New Δ%
CPU 37_251_711 30_837_131 -17.22%
Memory 144_343 131_619 -8.82%
Term Size 2_512 2_421 -3.62%
Flat Size 2_913 2_860 -1.82%

plutus-benchmark/lists/test/Sum/9.6/left-fold-data.eval.golden

Metric Old New Δ%
CPU 215_205_083 165_524_496 -23.09%
Memory 916_629 778_865 -15.03%
Term Size 142 129 -9.15%
Flat Size 711 701 -1.41%

plutus-benchmark/lists/test/Sum/9.6/right-fold-data.eval.golden

Metric Old New Δ%
CPU 220_005_083 170_324_496 -22.58%
Memory 946_629 808_865 -14.55%
Term Size 145 132 -8.97%
Flat Size 714 704 -1.40%

plutus-benchmark/script-contexts/test/V1/9.6/checkScriptContext1-20.eval.golden

Metric Old New Δ%
CPU 178_413_382 111_474_671 -37.52%
Memory 707_086 550_394 -22.16%
Term Size 1_190 956 -19.66%
Flat Size 1_644 1_465 -10.89%

plutus-benchmark/script-contexts/test/V1/9.6/checkScriptContext1-4.eval.golden

Metric Old New Δ%
CPU 50_962_790 32_459_423 -36.31%
Memory 201_646 156_122 -22.58%
Term Size 1_190 956 -19.66%
Flat Size 1_258 1_079 -14.23%

plutus-benchmark/script-contexts/test/V1/9.6/checkScriptContext2-20.eval.golden

Metric Old New Δ%
CPU 171_132_959 104_194_248 -39.12%
Memory 675_344 518_652 -23.20%
Term Size 1_133 899 -20.65%
Flat Size 1_569 1_390 -11.41%

plutus-benchmark/script-contexts/test/V1/9.6/checkScriptContext2-4.eval.golden

Metric Old New Δ%
CPU 48_885_695 30_382_328 -37.85%
Memory 192_336 146_812 -23.67%
Term Size 1_133 899 -20.65%
Flat Size 1_183 1_004 -15.13%

plutus-benchmark/script-contexts/test/V1/Data/9.6/checkScriptContext1-20.eval.golden

Metric Old New Δ%
CPU 8_111_579 7_827_595 -3.50%
Memory 33_498 33_434 -0.19%
Flat Size 641 642 +0.16%

plutus-benchmark/script-contexts/test/V1/Data/9.6/checkScriptContext1-4.eval.golden

Metric Old New Δ%
CPU 2_908_251 2_624_267 -9.76%
Memory 11_066 11_002 -0.58%
Flat Size 254 255 +0.39%

plutus-benchmark/script-contexts/test/V2/9.6/checkScriptContext1-20.eval.golden

Metric Old New Δ%
CPU 201_104_704 124_328_253 -38.18%
Memory 790_778 606_806 -23.26%
Term Size 1_247 1_013 -18.77%
Flat Size 1_754 1_575 -10.21%

plutus-benchmark/script-contexts/test/V2/9.6/checkScriptContext1-4.eval.golden

Metric Old New Δ%
CPU 57_377_504 36_906_589 -35.68%
Memory 228_378 177_398 -22.32%
Term Size 1_247 1_013 -18.77%
Flat Size 1_320 1_141 -13.56%

plutus-benchmark/script-contexts/test/V2/9.6/checkScriptContext2-20.eval.golden

Metric Old New Δ%
CPU 193_792_281 117_015_830 -39.62%
Memory 758_836 574_864 -24.24%
Term Size 1_188 954 -19.70%
Flat Size 1_678 1_499 -10.67%

plutus-benchmark/script-contexts/test/V2/9.6/checkScriptContext2-4.eval.golden

Metric Old New Δ%
CPU 55_268_409 34_797_494 -37.04%
Memory 218_868 167_888 -23.29%
Term Size 1_188 954 -19.70%
Flat Size 1_244 1_065 -14.39%

plutus-benchmark/script-contexts/test/V2/9.6/dataFwdStakeTrick.eval.golden

Metric Old New Δ%
CPU 5_482_022 4_914_248 -10.36%
Memory 9_278 9_150 -1.38%
Flat Size 1_180 1_182 +0.17%

plutus-benchmark/script-contexts/test/V2/9.6/dataFwdStakeTrickManual.eval.golden

Metric Old New Δ%
CPU 5_626_022 5_058_248 -10.09%
Memory 10_178 10_050 -1.26%
Flat Size 1_182 1_184 +0.17%

plutus-benchmark/script-contexts/test/V2/9.6/sopFwdStakeTrick.eval.golden

Metric Old New Δ%
CPU 250_275_304 145_894_198 -41.71%
Memory 969_390 724_058 -25.31%
Term Size 1_383 1_149 -16.92%
Flat Size 2_324 2_145 -7.70%

plutus-benchmark/script-contexts/test/V2/Data/9.6/checkScriptContext1-20.eval.golden

Metric Old New Δ%
CPU 8_241_242 7_957_258 -3.45%
Memory 33_830 33_766 -0.19%
Flat Size 705 706 +0.14%

plutus-benchmark/script-contexts/test/V2/Data/9.6/checkScriptContext1-4.eval.golden

Metric Old New Δ%
CPU 3_037_914 2_753_930 -9.35%
Memory 11_398 11_334 -0.56%
Flat Size 271 272 +0.37%

plutus-benchmark/script-contexts/test/V3/9.6/checkScriptContext1-20.eval.golden

Metric Old New Δ%
CPU 203_370_434 126_102_096 -37.99%
Memory 798_058 612_722 -23.22%
Term Size 2_191 1_827 -16.61%
Flat Size 2_644 2_365 -10.55%

plutus-benchmark/script-contexts/test/V3/9.6/checkScriptContext1-4.eval.golden

Metric Old New Δ%
CPU 60_411_234 39_448_432 -34.70%
Memory 240_458 188_114 -21.77%
Term Size 2_191 1_827 -16.61%
Flat Size 2_210 1_931 -12.62%

plutus-benchmark/script-contexts/test/V3/9.6/checkScriptContext2-20.eval.golden

Metric Old New Δ%
CPU 195_978_011 118_709_673 -39.43%
Memory 765_616 580_280 -24.21%
Term Size 2_127 1_763 -17.11%
Flat Size 2_566 2_287 -10.87%

plutus-benchmark/script-contexts/test/V3/9.6/checkScriptContext2-4.eval.golden

Metric Old New Δ%
CPU 58_222_139 37_259_337 -36.00%
Memory 230_448 178_104 -22.71%
Term Size 2_127 1_763 -17.11%
Flat Size 2_132 1_853 -13.09%

plutus-benchmark/script-contexts/test/V3/Data/9.6/checkScriptContext1-20.eval.golden

Metric Old New Δ%
CPU 8_241_242 7_957_258 -3.45%
Memory 33_830 33_766 -0.19%
Flat Size 711 712 +0.14%

plutus-benchmark/script-contexts/test/V3/Data/9.6/checkScriptContext1-4.eval.golden

Metric Old New Δ%
CPU 3_037_914 2_753_930 -9.35%
Memory 11_398 11_334 -0.56%
Flat Size 277 278 +0.36%

plutus-benchmark/script-contexts/test/V3/Data/9.6/purposeIsWellFormed-4.eval.golden

Metric Old New Δ%
CPU 23_349_930 19_611_399 -16.01%
Memory 80_962 79_830 -1.40%
Term Size 1_769 1_773 +0.23%
Flat Size 1_815 1_844 +1.60%

plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/currencySymbolValueOf.eval.golden

Metric Old New Δ%
CPU 13_284_190 11_438_876 -13.89%
Memory 28_690 28_274 -1.45%
Flat Size 290 291 +0.34%

plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq1.eval.golden

Metric Old New Δ%
CPU 397_258_060 339_163_895 -14.62%
Memory 1_037_005 998_845 -3.68%
Term Size 672 659 -1.93%
Flat Size 944 939 -0.53%

plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq2.eval.golden

Metric Old New Δ%
CPU 419_120_088 356_777_594 -14.87%
Memory 1_107_139 1_065_515 -3.76%
Term Size 672 659 -1.93%
Flat Size 995 990 -0.50%

plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq3.eval.golden

Metric Old New Δ%
CPU 437_002_138 370_496_887 -15.22%
Memory 1_160_257 1_111_429 -4.21%
Term Size 672 659 -1.93%
Flat Size 995 990 -0.50%

plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq4.eval.golden

Metric Old New Δ%
CPU 386_165_274 332_716_553 -13.84%
Memory 982_824 955_736 -2.76%
Term Size 672 659 -1.93%
Flat Size 951 946 -0.53%

plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq5.eval.golden

Metric Old New Δ%
CPU 411_423_571 351_276_383 -14.62%
Memory 1_071_776 1_031_900 -3.72%
Term Size 672 659 -1.93%
Flat Size 951 946 -0.53%

plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt1.eval.golden

Metric Old New Δ%
CPU 459_725_945 390_276_300 -15.11%
Memory 1_220_680 1_179_960 -3.34%
Term Size 1_065 1_052 -1.22%

plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt2.eval.golden

Metric Old New Δ%
CPU 419_488_088 357_145_594 -14.86%
Memory 1_109_439 1_067_815 -3.75%
Term Size 1_065 1_052 -1.22%

plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt3.eval.golden

Metric Old New Δ%
CPU 500_475_707 422_330_992 -15.61%
Memory 1_347_961 1_296_509 -3.82%
Term Size 1_065 1_052 -1.22%

plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt4.eval.golden

Metric Old New Δ%
CPU 386_533_274 333_084_553 -13.83%
Memory 985_124 958_036 -2.75%
Term Size 1_065 1_052 -1.22%

plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt5.eval.golden

Metric Old New Δ%
CPU 441_138_157 375_739_011 -14.83%
Memory 1_163_384 1_122_324 -3.53%
Term Size 1_065 1_052 -1.22%

plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/mintValueBurned.eval.golden

Metric Old New Δ%
CPU 26_700_791 21_732_429 -18.61%
Memory 113_530 112_410 -0.99%
Flat Size 275 276 +0.36%

plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/mintValueMinted.eval.golden

Metric Old New Δ%
CPU 21_784_369 17_383_587 -20.20%
Memory 94_800 93_808 -1.05%
Flat Size 264 265 +0.38%

plutus-tx-plugin/test/AsData/Budget/9.6/destructSum-manual.eval.golden

Metric Old New Δ%
CPU 6_889_454 6_401_583 -7.08%
Memory 24_823 25_195 +1.50%
Term Size 213 218 +2.35%
Flat Size 220 226 +2.73%

plutus-tx-plugin/test/AsData/Budget/9.6/destructSum.eval.golden

Metric Old New Δ%
CPU 6_841_454 6_353_583 -7.13%
Memory 24_523 24_895 +1.52%
Term Size 210 215 +2.38%
Flat Size 217 223 +2.76%

plutus-tx-plugin/test/AsData/Budget/9.6/onlyUseFirstField-manual.eval.golden

Metric Old New Δ%
CPU 510_574 368_582 -27.81%
Memory 1_728 1_696 -1.85%
Flat Size 31 32 +3.23%

plutus-tx-plugin/test/AsData/Budget/9.6/onlyUseFirstField.eval.golden

Metric Old New Δ%
CPU 510_574 368_582 -27.81%
Memory 1_728 1_696 -1.85%
Flat Size 31 32 +3.23%

plutus-tx-plugin/test/AsData/Budget/9.6/patternMatching.eval.golden

Metric Old New Δ%
CPU 3_887_113 3_745_121 -3.65%
Memory 12_140 12_108 -0.26%

plutus-tx-plugin/test/AsData/Budget/9.6/recordFields.eval.golden

Metric Old New Δ%
CPU 9_680_548 9_112_580 -5.87%
Memory 34_088 33_960 -0.38%

plutus-tx-plugin/test/Budget/9.6/map1.eval.golden

Metric Old New Δ%
CPU 169_395_592 155_773_381 -8.04%
Memory 324_042 320_970 -0.95%
Flat Size 336 337 +0.30%

plutus-tx-plugin/test/Budget/9.6/map2.eval.golden

Metric Old New Δ%
CPU 76_658_230 67_859_382 -11.48%
Memory 199_974 197_990 -0.99%
Flat Size 452 455 +0.66%

plutus-tx-plugin/test/Budget/9.6/map3.eval.golden

Metric Old New Δ%
CPU 129_231_286 112_163_732 -13.21%
Memory 347_904 335_284 -3.63%
Term Size 684 671 -1.90%
Flat Size 702 697 -0.71%

plutus-tx-plugin/test/Budget/9.6/matchAsDataE.eval.golden

Metric Old New Δ%
CPU 1_008_802 724_915 -28.14%
Memory 3_661 3_597 -1.75%
Flat Size 77 78 +1.30%

plutus-tx-plugin/test/Budget/9.6/toFromData.eval.golden

Metric Old New Δ%
CPU 5_641_857 3_182_422 -43.59%
Memory 20_224 13_404 -33.72%
Term Size 205 140 -31.71%
Flat Size 202 153 -24.26%

This comment will get updated when changes are made.

@SeungheonOh
Copy link
Collaborator Author

name using builtin using casing d%
pairFstSnd/2000 326.7 us 241.8 us -25.99%
pairFstSnd/4000 711.5 us 559.3 us -21.39%
pairFstSnd/6000 1.207 ms 982.7 us -18.58%
pairFstSnd/8000 1.727 ms 1.409 ms -18.41%
pairFstSnd/10000 2.278 ms 1.843 ms -19.10%
pairFstSnd/12000 2.795 ms 2.254 ms -19.36%
chooseUnit/2000 141.5 us 24.28 us -82.85%
chooseUnit/4000 311.5 us 48.23 us -84.52%
chooseUnit/6000 506.4 us 71.87 us -85.81%
chooseUnit/8000 730.5 us 95.73 us -86.89%
chooseUnit/10000 1.002 ms 119.9 us -88.04%
chooseUnit/12000 1.341 ms 141.8 us -89.43%
headList/2000 143.8 us 116.0 us -19.37%
headList/4000 302.6 us 237.1 us -21.67%
headList/6000 466.7 us 383.4 us -17.84%
headList/8000 655.3 us 553.8 us -15.49%
headList/10000 877.3 us 750.8 us -14.42%
headList/12000 1.090 ms 969.3 us -11.08%

Ran benchmark again locally, this compares implementation of headList, sndPair, and fstPair based on builtin casing to that based on builtins.

Copy link
Contributor

@effectfully effectfully left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great stuff, thank you.

I'm only confused why we allow more than 1 branch for casing on units, contrary to what the PR description says:

Casing on unit expects exactly one branch

Comment on lines 92 to 96
case
(equalsInteger
5
(case
tup
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, so case-of-case can be generalized such that it transforms, say,

case (nullList (case tup (\x y -> x : xs)))
  falseAlt
  trueAlt

into

case tup
  \x y ->
    case nullList (x : xs)
      falseAlt
      trueAlt

which then becomes

case tup
  \x y -> falseAlt

This wouldn't help here, but may or may not be a useful optimization in general.

Actually, we don't even need to care about the outer caseList, we just need to flip nullList and the inner case. Which is kinda what we do for ifThenElse. So yeah, it makes sense nullList is itself a glorified case.

And it works the other way too: case-of-nullList is as interesting to optimize as nullList-of-case. Obviously applies to other builtins like headList and fstPair etc. We do already handle ifThenElse (even though we don't actually generate it anymore), but only in one direction.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it makes sense nullList is itself a glorified case

Yeah, It can be literally just

case <list>
  (\_ _ -> falseCase)
  trueCase

Which I'm not entirely sure if it will be faster than builtin. I'll put this on my list to benchmark. Although it would be easier to keep nullList for optimization, I think.

I'm not entirely sure if this will improve anything drastically. IMO, we should wait until we figure out if builtin nullList is faster than casing nullList and proceed accordingly.

Comment on lines 6218 to 6227
(case
tup
[ (\l
r ->
r) ]))
(case
tup
[ (\l
r ->
l) ]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we should cache these two somehow? They appear quite a few times in the file.

@@ -568,6 +577,11 @@ instance CaseBuiltin DefaultUni where
[] -> Right $ HeadOnly $ branches Vector.! 1
(y : ys) -> Right $ headSpine (branches Vector.! 0) [someValueOf ty y, someValueOf uni ys]
| otherwise -> Left $ outOfBoundsErr someVal branches
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I thought we've discussed it, but perhaps it was something else. We should have a CaseResult data type that is properly strict and removes the Either indirection that we have here.

It'll mean adding a constructor for errors to HeadSpine, since we only use that for casing on constants nowadays anyway.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will make a separate optimization PR

@SeungheonOh SeungheonOh enabled auto-merge (squash) September 2, 2025 07:16
@SeungheonOh SeungheonOh merged commit c42ff4f into master Sep 2, 2025
8 checks passed
@SeungheonOh SeungheonOh deleted the sho/6602-unitpair branch September 2, 2025 08:43
Unisay pushed a commit that referenced this pull request Oct 1, 2025
* Add constant casing for unit and pair, make builtin use constant casing

* Update goldens

* changelog

* Add benchmark for comparing Pair/Unit builtins to casing

* Add headList builtin vs casing bench

* comments

* Add conformance test for pair/unit casing

* casing unit should only allow single branch

* tidy

* Add `casePair` and make `fromOpaque` use it

* Make `FromData` use case pair

* blacklist pair/unit casing conformance on agda
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add casing on pairs and unit

2 participants