Skip to content

Conversation

daxfohl
Copy link
Collaborator

@daxfohl daxfohl commented Sep 12, 2025

This PR improves the resilience of the cached member fields in Circuit. Most importantly, _placement_cache, which is used to speed up Circuit.append() from O(N) to O(1), is made to be resilient and consistent across insert and batch inserts, freeze/unfreeze cycles, add and mul operations, and copy. Prior to this PR, performing any of those actions on a circuit would delete the cache, and append would fall back to O(N) behavior from that point on.

Summary of changes:

  • _PlacementCache has new methods insert_moment(index, count) and put(index, mop), that update the key indices to account for new moments or operations. Circuit has new corresponding _insert_moments(...) and _put_ops(...) methods to modify the circuit and update the cache atomically, and logic strewn around Circuit has been updated to use those methods when possible.
  • Circuit.copy() now preserves all cache values.
  • All cached values except _placement_cache are now immutable types, so copy doesn't have to make copies.
  • A simple optimization to Moment.with_operations(*ops) gave a 15% speedup in the common case of len(ops)==1.

Overall, the performance of append and insert individually are unaffected by this change; measured time is equal, but the performance when mixing inserts and appends is improved from O(N) to O(1). It also cleans up the code a bit IMO, with less need to place self._mutated() everywhere.

The biggest open question I have is whether building the placement cache in Circuit.from_moments() justifies the extra latency. If not, that could be removed, and it would only affect the freeze/unfreeze cycle case. Update: it does not, and that functionality has been reverted.

Fixes #7464

@github-actions github-actions bot added the size: L 250< lines changed <1000 label Sep 12, 2025
@daxfohl
Copy link
Collaborator Author

daxfohl commented Sep 12, 2025

Okay, I lean toward not making the change in _from_moments. I see a lot of places across the codebase that uses _from_moments or unfreeze to make a quick copy of a circuit, edit some operations (which would destroy the cache anyway), and then copy the result back or re-freeze it. Therefore _from_moments needs to be as fast as possible.

At some point, it would be possible to add a parameter to allow each use case to choose whether to create the cache or not, but that would be a separate PR.

Copy link

codecov bot commented Sep 12, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.37%. Comparing base (97781c7) to head (d347a26).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7649   +/-   ##
=======================================
  Coverage   99.37%   99.37%           
=======================================
  Files        1078     1078           
  Lines       96162    96230   +68     
=======================================
+ Hits        95559    95627   +68     
  Misses        603      603           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@daxfohl
Copy link
Collaborator Author

daxfohl commented Sep 12, 2025

Updated PR to undo the change to _from_moments and also Circuit(*moments) constructor to be safe. You can click on the diff link to see how it affects tests. Basically just the freeze cycles don't retain the cache, and of course manually calling from_moments creates a circuit without a placement cache.

@daxfohl daxfohl marked this pull request as ready for review September 12, 2025 06:56
@daxfohl daxfohl requested review from vtomole and a team as code owners September 12, 2025 06:56
@daxfohl daxfohl changed the title Improve circuit cache resilience Preserve cached values in Circuit more granularly Sep 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size: L 250< lines changed <1000
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Optimize circuit construction when Insert is used
1 participant