⚡️ Speed up method CallbackRegistry.disconnect by 918%
#212
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
📄 918% (9.18x) speedup for
CallbackRegistry.disconnectinlib/matplotlib/cbook.py⏱️ Runtime :
16.8 milliseconds→1.65 milliseconds(best of40runs)📝 Explanation and details
The optimization achieves a 918% speedup by eliminating expensive list conversions and reducing O(n) loops to O(1) dictionary lookups in the
disconnectmethod.Key optimizations:
Removed unnecessary
list()conversion: Changedlist(self.callbacks.items())toself.callbacks.items(). The original creates a full copy of all callback entries unnecessarily, while the optimized version iterates directly over the dictionary view.Eliminated O(n) proxy search loop: Replaced the expensive
for (current_proxy, current_cid) in list(proxy_to_cid.items())loop with a directproxy_to_cid.get(proxy)lookup. This changes an O(n) scan through all proxies to an O(1) dictionary lookup.Why this provides massive speedups:
List conversion overhead: The original
list(self.callbacks.items())creates unnecessary memory allocations and copies. Line profiler shows 1.74ms (1% of time) spent on this single operation.Quadratic behavior elimination: The original code's nested loop structure meant that for each callback disconnection, it would scan through ALL proxy-to-cid mappings. With many callbacks (500-1000 in test cases), this becomes O(n²) behavior. The optimization reduces this to O(1).
Memory pressure reduction: Avoiding list conversions reduces memory allocation/deallocation overhead, which is particularly beneficial when called frequently.
Test case performance patterns:
The optimizations are particularly effective for applications with many registered callbacks, which is common in matplotlib's event-driven architecture where disconnect operations may be called frequently during cleanup or dynamic UI updates.
✅ Correctness verification report:
🌀 Generated Regression Tests and Runtime
To edit these changes
git checkout codeflash/optimize-CallbackRegistry.disconnect-misb8wy5and push.