Commit 40757fe
authored
Optimize Fibonacci.fibonacci
Runtime improvement (primary): The optimized version cuts execution time from ~169 ms to ~84.2 µs — a ~200k% speedup — by replacing the exponential recursive routine with an O(log n) iterative algorithm.
What changed (specific optimizations)
- Replaced naive recursion: removed fibonacci(n-1)+fibonacci(n-2) which performs an exponential number of function calls and repeated work.
- Implemented the fast-doubling method iteratively: processes the bits of n (highest to lowest) and computes F(2k) and F(2k+1) via closed-form recurrences in a tight loop.
- Eliminated recursion and allocations: uses two long locals (a, b) and simple arithmetic and bit operations (<<, >>, &), with no extra objects or call-stack growth.
- Minimizes loop iterations by computing the highest set bit once (Integer.numberOfLeadingZeros) and looping only ~log2(n) times.
Why this yields the big speedup
- Algorithmic complexity: original is exponential in n (lots of redundant subcalls); fast-doubling runs in O(log n) arithmetic steps. For moderate/large n (tests use up to n=30 and beyond), that change dominates runtime.
- Removes call overhead and duplicate computation: the profiler shows the original version incurred tens of millions of line hits (huge call/return traffic). The optimized version does only a small constant number of operations per bit of n, so total operations collapse dramatically.
- CPU-friendly operations: arithmetic and bitwise operations are fast and branch-predictable; the loop body has a small fixed amount of work and straightforward branches, which modern JITs optimize well.
Behavioral/compatibility notes (key impacts)
- Correctness preserved for inputs in the same long-typed semantics: negative input still throws; base cases n <= 1 return immediately.
- Stack-safety: recursion is gone — no risk of deep recursion or stack overflow for large n.
- Overflow semantics unchanged: the function still returns long and will overflow in the same way as the original recursive version for very large n (no change in numeric range handling).
- No new dependencies or allocations introduced; the function remains self-contained and lightweight.
Where this matters (workloads/tests)
- Hot paths and repeated calls: any code that repeatedly computes Fibonacci numbers (e.g., per-request, inside loops, or batch processing) will see large throughput and latency wins because per-call cost is tiny.
- Larger n and performance-guarded tests: annotated tests (e.g., n=30, performance/timeouts) show the biggest wins — the optimized version runs orders of magnitude faster and easily satisfies timeouts.
- Small n still fast: base cases are checked early, so there’s no regression for tiny inputs; tests for n=0..10 show microsecond or sub-microsecond times.
Trade-offs and cautions
- No regression in runtime; this change was accepted specifically for runtime improvement.
- Keep the same numeric type expectations: if callers relied on detecting overflow by observing negative/wrapped long results, behavior remains the same so tests remain valid.
- The implementation uses int bit operations to iterate bits of n; since n is an int, the loop bounds are correct and base cases handle n==0/1.
Line-profiler evidence
- Original profiler: huge total time and tens of millions of line hits caused by recursion.
- Optimized profiler: total time collapsed to microseconds and line hits are small and concentrated in the iterative loop lines, matching the expected O(log n) behavior.
Bottom line: this replaces an exponential-time recursive implementation with an iterative fast-doubling algorithm, producing the dramatic runtime improvement shown by the profiler and tests while preserving semantics and removing recursion-related risks.1 parent 04b0dbd commit 40757fe
1 file changed
Lines changed: 21 additions & 1 deletion
Lines changed: 21 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
24 | | - | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
25 | 45 | | |
26 | 46 | | |
27 | 47 | | |
| |||
0 commit comments