Skip to content

feat: iterative Fibonacci implementation in Plinth (2,511x faster)#144

Merged
Unisay merged 3 commits intomainfrom
yura/issue-92-iterative-fibonacci-plinth
Nov 7, 2025
Merged

feat: iterative Fibonacci implementation in Plinth (2,511x faster)#144
Unisay merged 3 commits intomainfrom
yura/issue-92-iterative-fibonacci-plinth

Conversation

@Unisay
Copy link
Collaborator

@Unisay Unisay commented Nov 7, 2025

Summary

Creates an iterative Fibonacci submission in Plinth that achieves 2,511x overall performance improvement over naive recursion, using an O(n) accumulator-based approach.

Implementation Details

Algorithm

  • Approach: Iterative with tail recursion using accumulators
  • Time Complexity: O(n) (vs O(2^n) for naive recursion)
  • Space Complexity: O(1)
  • Pattern: Helper function fibonacciLoop maintains (prev, curr) accumulators

Code Structure

  • New module: lib/FibonacciIterative.hs
  • Build system: Updated cape.cabal and plinth-submissions-app/Main.hs
  • Submission: submissions/fibonacci/Plinth_1.45.0.0_Unisay/

Performance Results

Key Metrics

Metric Iterative Naive Recursion Improvement
fib(25) CPU 23.4M 194.2B 8,299x
Total CPU 85M 213.5B 2,511x
Total Memory 358K 882.2M 2,464x
Script Size 73 bytes 73 bytes Same

Comparison with Other Compilers

  • OpShin (iterative): 240M CPU (729x improvement)
  • Aiken (tail-recursive): 67.8M CPU (3,000x improvement)
  • Plinth (iterative): 85M CPU (2,511x improvement)

Testing

  • ✅ All 11 test cases pass (fibonacci 0-25, negative)
  • ✅ Schema validation passed (metadata.json, metrics.json)
  • ✅ cape test: 53/53 passed
  • ✅ cabal test: 222/222 passed
  • cape submission verify passed

Files Changed

cape.cabal                                          # Added FibonacciIterative to exposed-modules
lib/FibonacciIterative.hs                          # New iterative implementation
plinth-submissions-app/Main.hs                     # Added compilation for new module
submissions/fibonacci/Plinth_1.45.0.0_Unisay/      # Complete submission structure
├── fibonacci.uplc
├── metadata.json
├── metrics.json
├── README.md
└── source/FibonacciIterative.hs

Acceptance Criteria

All criteria from issue #92 met:

  • ✅ Passes all tests in cape-tests.json (11/11)
  • ✅ Uses iterative approach (not naive recursion)
  • ✅ Achieves <1B CPU units total (85M - well under target!)
  • ✅ Follows Plinth submission structure conventions
  • ✅ Includes source code for reproducibility
  • cape submission verify passes
  • ✅ Ready for cape submission report to generate updated charts

Resolves #92

## Implementation

Created iterative Fibonacci submission achieving O(n) time complexity
using accumulator-based approach with tail recursion:

- New module: lib/FibonacciIterative.hs
- Uses helper function fibonacciLoop with accumulators (prev, curr)
- Avoids exponential recalculation of values

## Performance Results

Achieved 2,511x overall performance improvement:
- fibonacci(25): 23.4M CPU (vs 194.2B naive - 8,299x faster)
- Total CPU: 85M units (vs 213.5B naive)
- Total Memory: 358K units (vs 882.2M naive - 2,464x better)
- Script size: 73 bytes

## Submission Structure

submissions/fibonacci/Plinth_1.45.0.0_Unisay/
├── fibonacci.uplc (compiled UPLC program)
├── metadata.json (compiler metadata)
├── metrics.json (performance measurements)
├── README.md (implementation notes)
└── source/FibonacciIterative.hs (source code)

## Testing

- All 11 test cases pass (fibonacci 0-25, negative)
- Schema validation passed (metadata.json, metrics.json)
- cape test: 53/53 passed
- cabal test: 222/222 passed

Resolves #92
@Unisay Unisay self-assigned this Nov 7, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Nov 7, 2025

🚀 PR Preview Deployed

Preview URL: https://intersectmbo.github.io/UPLC-CAPE/pr-144/

The preview site is automatically updated on every push to this PR and will be removed when the PR is closed.

## Experiment Summary

Tested 5 source-level optimization variants to reduce UPLC execution budget:
- V2: Countdown + equality check
- V3: Case expressions instead of guards
- V4: Compare to zero
- V5: Combined (countdown + case)
- V6: Explicit strictness (bang patterns)

## Results

| Variant | Total CPU | vs Original | Script Size | Verdict |
|---------|-----------|-------------|-------------|---------|
| Original | 85.09M | baseline | 73 bytes | ✅ BEST |
| V2 | 85.09M | +0.004% | 117 bytes | ❌ |
| V3 | 85.09M | 0% | 73 bytes | ⚠️ No change |
| V4 | 84.53M | -0.65% | 117 bytes | ❌ Script bloat |
| V5 | 88.01M | +3.4% | 135 bytes | ❌ WORSE |
| V6 | 92.00M | +8.1% | 122 bytes | ❌ MUCH WORSE |

## Key Findings

- **Case expressions = Guards**: PlutusTx compiles both to identical UPLC
- **Strictness hurts**: Bang patterns add 8% CPU overhead
- **Countdown adds bloat**: Extra edge case guards increase script size 60%
- **Minimal CPU gains**: Best improvement (V4) only 0.65% but 60% larger script
- **Original is optimal**: No source-level optimization provides meaningful benefit

## Conclusion

Original FibonacciIterative.hs implementation is already optimal for PlutusTx.
Further improvements require compiler-level changes (Y-combinator elimination,
native case support), not source code modifications.

## Cleanup

Removed all experimental variant files and reverted build configuration.
@Unisay
Copy link
Collaborator Author

Unisay commented Nov 7, 2025

Optimization Experiment Results

Tested 5 source-level optimizations to further reduce execution budget:

Tested Variants

  1. V2: Countdown + equality check
  2. V3: Case expressions instead of guards
  3. V4: Compare to zero
  4. V5: Combined (countdown + case expressions)
  5. V6: Explicit strictness (bang patterns)

Performance Comparison

Variant Total CPU vs Original Script Size Verdict
Original 85.09M baseline 73 bytes BEST
V2 85.09M +0.004% 117 bytes (+60%) ❌ No benefit
V3 85.09M 0% 73 bytes ⚠️ Identical
V4 84.53M -0.65% 117 bytes (+60%) ❌ Minimal gain, bloat
V5 88.01M +3.4% 135 bytes (+85%) ❌ WORSE
V6 92.00M +8.1% 122 bytes (+67%) ❌ MUCH WORSE

Key Findings

  1. Case expressions = Guards: PlutusTx compiles both to identical UPLC - no difference
  2. Strictness hurts: Bang patterns (!prev !curr) add 8% CPU overhead
  3. Countdown adds bloat: Extra edge case guards increase script size by 60%
  4. Minimal CPU gains: Best improvement (V4) only 0.65%, but script size grows 60%
  5. Original is optimal: No source-level optimization provides meaningful benefit

Conclusion

The original implementation is already optimal for PlutusTx. No source-level changes were applied.

To close the performance gap with Aiken (67.8M CPU) would require compiler-level improvements:

  • Y-combinator elimination
  • Native case instead of ifThenElse builtin
  • Better recursion pattern generation

These are outside the scope of source code changes and would require enhancements to the PlutusTx compiler itself.

Bottom line: The 2,511x improvement over naive recursion is already excellent. The remaining 20% gap with Aiken reflects the trade-off between PlutusTx's general-purpose compiler and Aiken's UPLC-specialized compiler.

Renamed submissions/fibonacci/Plinth_1.45.0.0_Unisay to
submissions/fibonacci/Plinth_1.45.0.0_Unisay_tailrec to:
- Match naming convention of Aiken_tailrec submission
- Clearly indicate tail-recursive/iterative implementation
- Distinguish from naive recursive baseline

Updated plinth-submissions-app to generate to new path.
@Unisay Unisay merged commit 79a4003 into main Nov 7, 2025
3 checks passed
@Unisay Unisay deleted the yura/issue-92-iterative-fibonacci-plinth branch November 7, 2025 16:31
github-actions bot added a commit that referenced this pull request Nov 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create iterative Fibonacci submission in Plinth

1 participant