Skip to content

Sorted timestamps optimization #507

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

devbugging
Copy link
Contributor

Closes: #502

Summary

Optimizes the process() function in FlowCallbackScheduler by replacing expensive map filtering with efficient sorted timestamp management, significantly reducing computation when called frequently with no pending work.

Changes:

  • New SortedTimestamps struct: Encapsulates sorted timestamp logic with clean API (add(), remove(), past(), check())
  • Early exit optimization: check() method enables immediate return when no callbacks need processing
  • Efficient traversal: past() method returns only timestamps needing processing without filtering entire map
  • Automatic maintenance: Timestamps added during scheduling, removed during cleanup
  • Comprehensive tests: Table-driven tests covering all methods and edge cases

Performance Impact

  • Before: O(n) map filtering on every process() call where n = total scheduled slots
  • After: O(1) early exit when no work needed, O(k) traversal where k = past timestamps only
  • Benefit: Dramatically faster when process() called frequently with no pending callbacks

Testing

Added isolated unit tests for SortedTimestamps struct.

@devbugging devbugging changed the base branch from master to feature/callback-scheduling August 8, 2025 09:29
@joshuahannan joshuahannan changed the base branch from feature/callback-scheduling to josh/failed-callbacks August 11, 2025 14:54
@joshuahannan joshuahannan deleted the branch onflow:josh/failed-callbacks August 11, 2025 18:01
Copy link
Member

@joshuahannan joshuahannan left a comment

Choose a reason for hiding this comment

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

looks great!

@@ -308,6 +308,67 @@ access(all) contract FlowCallbackScheduler {
}
}

/// SortedTimestamps maintains a sorted array of timestamps for efficient processing
Copy link
Member

Choose a reason for hiding this comment

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

Most of this is pretty generic. I wish we could just put this in an ArrayUtils contract that is separate from this so we don't have all this sorting stuff cluttering up this contract, but that might not really be worth putting together

}
insertIndex = i + 1
}
self.timestamps.insert(at: insertIndex, timestamp)
Copy link
Member

Choose a reason for hiding this comment

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

wow, I didn't even realize this was possible. This is great!

}

/// Get all timestamps that are in the past (less than or equal to current timestamp)
access(all) fun past(current: UFix64): [UFix64] {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
access(all) fun past(current: UFix64): [UFix64] {
access(all) fun getPast(current: UFix64): [UFix64] {


/// Check if there are any timestamps that need processing
/// Returns true if processing is needed, false for early exit
access(all) fun check(current: UFix64): Bool {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
access(all) fun check(current: UFix64): Bool {
access(all) fun checkIfTimestampsNeedProcessing(current: UFix64): Bool {

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.

Optimise callback scheduler process
2 participants