Skip to content

Release 0.9.1

Choose a tag to compare

@OutSquareCapital OutSquareCapital released this 15 Jan 02:15
· 28 commits to master since this release

πŸš€ pyochain 0.9.1 β€” Release Notes

Date: 2026-01-15 πŸ“…

πŸ†• Highlights

This release is a critical bugfix and performance improvement release:

  • CRITICAL FIX: Fixed a severe performance regression introduced in 0.7.0 where iterating over Iter objects fell back to slow __next__() calls instead of delegating to the underlying iterator. Up to 10x faster.
  • Rust Migration: Moved try_find implementation to Rust β€” Achieving +15-30% speedup across all use cases.
  • Code Quality: Various internal Rust code improvements for maintainability.
  • Documentation: Fixes on API reference generation. Website is now live again.

πŸ› Critical Bug Fix

Iter Performance Regression

Issue: After migrating to abstract traits in 0.7.0, the Iter.__iter__() method was accidentally removed.
This caused Python to fall back to calling __next__() repeatedly when Iter objects were passed to functions expecting Iterator objects, resulting in dramatically slower performance.

Expected behavior: Iter wraps any iterable and converts it to an iterator by calling iter() on it, storing the result in self._inner. When Iter.__iter__() is called, it should directly return self._inner rather than self. This delegation is crucial because:

  • It bypasses Iter's Python-level __next__() implementation
  • The underlying iterator's native (often C-level) __next__() is called instead
  • This allows maximum efficiency regardless of the original iterable type (list, tuple, generator, etc.)

Fix: Restored Iter.__iter__() to properly delegate to self._inner, restoring original performance characteristics. Also explicitly calls __iter__() in PyoIterator provided methods as additional safeguard.

Impact: Any code passing Iter objects to functions that iterate over them (e.g., list(iter_obj), tuple(iter_obj), func(iter_obj) where func iterates) will see performance return to expected levels.


πŸš€ Performance Improvements

try_find Migration to Rust

Moved Iter.try_find() implementation from Python to Rust for better performance across all scenarios:

┏━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Category ┃ Operation                   ┃ Rust (s, median) ┃ Python (s, median) ┃ Speedup ┃
┑━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
β”‚ try_find β”‚ find_at_middle              β”‚           0.0067 β”‚             0.0087 β”‚   1.30x β”‚
β”‚ try_find β”‚ find_at_end                 β”‚           0.0132 β”‚             0.0163 β”‚   1.24x β”‚
β”‚ try_find β”‚ find_not_found              β”‚           0.0148 β”‚             0.0168 β”‚   1.14x β”‚
β”‚ try_find β”‚ find_error_late             β”‚           0.0143 β”‚             0.0171 β”‚   1.20x β”‚
β”‚ try_find β”‚ find_with_complex_predicate β”‚           0.0020 β”‚             0.0025 β”‚   1.23x β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Median speedup: 1.23x
Rust wins: 5/5

This act as a proof-of-concept for further migrations of iteration algorithms which are not calling Python itertools, builtins functions, or cytoolz functions (as those are already very efficient).