GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||
GeezerVison is showing github.com — GH-96793: Specialize FOR_ITER for generators. by markshannon · Pull Request #98772 · python/cpython Conversation
|
|
There is a bug in this. It doesn't set the |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
https://github.com/python/cpython/compare/main...faster-cpython:cpython:specialize-for-iter-gen-handle-exc-stack?expand=1 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| frame->frame_obj = NULL; | ||
| frame->prev_instr = _PyCode_CODE(code) - 1; | ||
| frame->is_entry = false; | ||
| frame->yield_offset = 0; |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Why is this called "yield_offset", is it not the relative offset to jump by when the generator is exhausted? (the same as the arg to FOR_ITER?)
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Because it's the offset for YIELD_VALUE to return to relative to RETURN_VALUE
https://github.com/python/cpython/pull/98772/files#diff-c22186367cbe20233e843261998dc027ae5f1f8c0d2e778abfa454ae74cc59deR2087
Sorry, something went wrong.
There was an error while loading. Please reload this page.
You can run https://github.com/python/pyperformance/blob/main/pyperformance/data-files/benchmarks/bm_generators/run_benchmark.py, it is specifically designed to benchmark generators (microbenchmark). |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
I'll run that benchmark if pyperformance ever does another release. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
I'm seeing a 35% speedup on this benchmark: Tree iteratorimport timeit class Tree: def __init__(self, left, value, right): self.left = left self.value = value self.right = right def __iter__(self): if self.left: for item in self.left: yield item yield self.value if self.right: for item in self.right: yield item def tree(input: range) -> Tree | None: n = len(input) if n == 0: return None i = n // 2 return Tree(tree(input[:i]), input[i], tree(input[i + 1:])) def setup(): global iterable assert list(tree(range(10))) == list(range(10)) iterable = tree(range(100000)) print(timeit.timeit("for _ in iterable: pass", "setup()", globals=globals(), number=10)) Note that this uses And a 36% speedup on this one: Flat iteratorimport timeit class RangeWrapper: def __init__(self, n): self.r = range(n) def __iter__(self): for item in self.r: yield item def setup(): global iterable iterable = RangeWrapper(1000000) print(timeit.timeit("for _ in iterable: pass", "setup()", globals=globals(), number=10)) Comparing the fastest of 6 runs for main and this PR. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Co-authored-by: Irit Katriel <[email protected]>
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.