Skip to content

perf(#34): hoist find_next_pending_index to eliminate O(N²) gas complexity in get_all_milestones_view#67

Open
d3vobed wants to merge 1 commit into
OrbitChainLabs:mainfrom
d3vobed:fix/hoist-find-next-pending-index
Open

perf(#34): hoist find_next_pending_index to eliminate O(N²) gas complexity in get_all_milestones_view#67
d3vobed wants to merge 1 commit into
OrbitChainLabs:mainfrom
d3vobed:fix/hoist-find-next-pending-index

Conversation

@d3vobed

@d3vobed d3vobed commented Jun 22, 2026

Copy link
Copy Markdown

Summary

get_all_milestones_view called views::get_milestone_by_index for each milestone, and get_milestone_by_index invoked find_next_pending_index which linearly scanned every milestone to find the first non-released one. With N milestones this produced N + (N × N) ≈ N² storage reads.

Change

Hoist find_next_pending_index — compute it once at the top of get_all_milestones_view and inline the MilestoneView construction, reusing the precomputed value for is_next_pending:

Before After
for i in 0..Nget_milestone_by_indexfind_next_pending_index (full scan) next_pending = find_next_pending_index(env) (1 scan)
for i in 0..Nnext_pending == i (O(1))
O(N²) storage reads O(N) storage reads

The same fix can be applied to any other view function that iterates milestones and per-row calls find_next_pending_index.

Verification

  • Behaviour unchangedis_next_pending semantics are identical (same comparison, same value)
  • All 142 tests pass (including existing snapshot fixtures for get_all_milestones)
  • No public API changes — function signature and MilestoneView shape are untouched

Closes #34

…(N²) gas complexity in get_all_milestones_view

get_all_milestones_view called views::get_milestone_by_index per
milestone, and get_milestone_by_index invoked find_next_pending_index
which linearly scanned every milestone to find the first non-released
one.  With N milestones this produced N + (N × N) ≈ N² storage reads.

Fix: call find_next_pending_index once at the top of
get_all_milestones_view and inline the MilestoneView construction
in the loop, reusing the precomputed value for is_next_pending.

Behavioural semantics of is_next_pending are unchanged —
identical comparison, identical result.

All 142 tests pass, including existing snapshot fixtures.

Closes OrbitChainLabs#34
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.

[LOW] get_all_milestones has O(N²) gas complexity from redundant find_next_pending_index scans

1 participant