-
Notifications
You must be signed in to change notification settings - Fork 46
Backport fixes to as_completed and map iterators (bpo-27144) #66
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
|
@agronholm As you mentioned you are busy, here you have a reproducer with output from runs before and after the changes in this PR. Note how the count (and obviously memory footprint) of Reproducer script: # file: reproducer.py
import gc
import time
from pympler import summary
from pympler import muppy
from concurrent.futures import ThreadPoolExecutor, as_completed
def random_data(*args):
time.sleep(1)
return bytearray(1024*1024*2)
def gen_executor0():
with ThreadPoolExecutor(1) as executor:
futures = [executor.submit(random_data) for x in range(5)]
for future in as_completed(futures):
futures.remove(future)
future = None
yield
def gen_executor1():
with ThreadPoolExecutor(1) as executor:
for y in executor.map(random_data, range(5)):
y = None
yield
def main(gen_executor):
for cycle in gen_executor():
gc.collect()
summary.print_(summary.summarize(muppy.get_objects()), limit=4)
if __name__ == '__main__':
print("as_completed()")
main(gen_executor0)
print("executor.map()")
main(gen_executor1)Run before this PR: $ python reproducer.py
as_completed()
types | # objects | total size
=========== | =========== | ============
bytearray | 1 | 2.00 MB
dict | 767 | 1.14 MB
str | 8468 | 803.97 KB
code | 2595 | 324.38 KB
types | # objects | total size
=========== | =========== | ============
bytearray | 2 | 4.00 MB
dict | 768 | 1.14 MB
str | 8468 | 803.97 KB
code | 2595 | 324.38 KB
types | # objects | total size
=========== | =========== | ============
bytearray | 3 | 6.00 MB
dict | 767 | 1.14 MB
str | 8468 | 803.97 KB
code | 2595 | 324.38 KB
types | # objects | total size
=========== | =========== | ============
bytearray | 4 | 8.00 MB
dict | 766 | 1.14 MB
str | 8468 | 803.97 KB
code | 2595 | 324.38 KB
types | # objects | total size
=========== | =========== | ============
bytearray | 5 | 10.00 MB
dict | 765 | 1.14 MB
str | 8466 | 803.89 KB
code | 2595 | 324.38 KB
executor.map()
types | # objects | total size
=========== | =========== | ============
bytearray | 1 | 2.00 MB
dict | 766 | 1.14 MB
str | 8465 | 803.84 KB
code | 2596 | 324.50 KB
types | # objects | total size
=========== | =========== | ============
bytearray | 2 | 4.00 MB
dict | 765 | 1.14 MB
str | 8465 | 803.84 KB
code | 2596 | 324.50 KB
types | # objects | total size
=========== | =========== | ============
bytearray | 3 | 6.00 MB
dict | 764 | 1.14 MB
str | 8465 | 803.84 KB
code | 2596 | 324.50 KB
types | # objects | total size
=========== | =========== | ============
bytearray | 4 | 8.00 MB
dict | 763 | 1.14 MB
str | 8465 | 803.84 KB
code | 2596 | 324.50 KB
types | # objects | total size
=========== | =========== | ============
bytearray | 5 | 10.00 MB
dict | 762 | 1.14 MB
str | 8463 | 803.76 KB
code | 2596 | 324.50 KBRun after this PR: $ python reproducer.py
as_completed()
types | # objects | total size
======= | =========== | ============
dict | 765 | 1.14 MB
str | 8470 | 804.44 KB
code | 2596 | 324.50 KB
type | 167 | 148.64 KB
types | # objects | total size
======= | =========== | ============
dict | 764 | 1.14 MB
str | 8470 | 804.44 KB
code | 2596 | 324.50 KB
type | 167 | 148.64 KB
types | # objects | total size
======= | =========== | ============
dict | 761 | 1.14 MB
str | 8470 | 804.44 KB
code | 2596 | 324.50 KB
type | 167 | 148.64 KB
types | # objects | total size
======= | =========== | ============
dict | 758 | 1.13 MB
str | 8470 | 804.44 KB
code | 2596 | 324.50 KB
type | 167 | 148.64 KB
types | # objects | total size
======= | =========== | ============
dict | 755 | 1.13 MB
str | 8461 | 804.04 KB
code | 2596 | 324.50 KB
type | 167 | 148.64 KB
executor.map()
types | # objects | total size
======= | =========== | ============
dict | 764 | 1.14 MB
str | 8467 | 804.30 KB
code | 2597 | 324.62 KB
type | 167 | 148.64 KB
types | # objects | total size
======= | =========== | ============
dict | 761 | 1.14 MB
str | 8467 | 804.30 KB
code | 2597 | 324.62 KB
type | 167 | 148.64 KB
types | # objects | total size
======= | =========== | ============
dict | 758 | 1.13 MB
str | 8467 | 804.30 KB
code | 2597 | 324.62 KB
type | 167 | 148.64 KB
types | # objects | total size
======= | =========== | ============
dict | 755 | 1.13 MB
str | 8467 | 804.30 KB
code | 2597 | 324.62 KB
type | 167 | 148.64 KB
types | # objects | total size
======= | =========== | ============
dict | 752 | 1.13 MB
str | 8458 | 803.91 KB
code | 2597 | 324.62 KB
type | 167 | 148.64 KB |
agronholm
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two oddities, otherwise looks good.
| yield future | ||
| for f in _yield_finished_futures(finished, waiter, | ||
| ref_collect=(fs,)): | ||
| f = [f] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this? Why not just yield f?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhh...because otherwise the future would still be referenced by the generator. Gotcha.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. Maybe Python 4 will consider fixing iteration target vars leaking to the scope :-).
| finished.reverse() | ||
| for f in _yield_finished_futures(finished, waiter, | ||
| ref_collect=(fs, pending)): | ||
| f = [f] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto
|
Thank you very much! |
Python issues:
concurrent.futures.as_completed()python/cpython#3830