-
Notifications
You must be signed in to change notification settings - Fork 12
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
Add our version of the std lib's "worker pool" #176
Conversation
examples/concurrent_actors_primes.py
Outdated
for i in range(workers): | ||
|
||
# this starts a new sub-actor (process + trio runtime) and | ||
# stores it's "portal" for later use to "submit jobs" (ugh). |
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.
typo it's
..
examples/concurrent_actors_primes.py
Outdated
portals.append( | ||
await tn.start_actor( | ||
f'worker_{i}', | ||
rpc_module_paths=[__name__], |
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.
I was thinking about changing this name to exposed_modules
.. what y'all think?
examples/concurrent_actors_primes.py
Outdated
async def map( | ||
worker_func: Callable[[int], bool], | ||
sequence: List[int] | ||
) -> List[bool]: |
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.
gah should be List[Tuple[int, bool]]
pretty sure
examples/concurrent_actors_primes.py
Outdated
# define an async (local) task to collect results from workers | ||
async def collect_portal_result(func, value, portal): | ||
|
||
results.append((value, await portal.run(func, n=value))) |
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.
This is a use case for keeping sync functions as per #77?
I realize we could just have wrapped func
here inside an async function wrapper - is the extra overhead something we should help avoid? does it really matter?
examples/concurrent_actors_primes.py
Outdated
portal | ||
) | ||
|
||
return results |
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.
We could offer an incremental yielding system here but it will require adding a trio
mem channel.
Not sure if this will make the example too complicated?
with concurrent.futures.ProcessPoolExecutor() as executor: | ||
start = time.time() | ||
|
||
for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)): |
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.
techincally this is yielding results as they arrive underneath so I guess to be fair we should do that too?
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.
I definitely agree with this. It is trivial for a user to reorder their results when necessary from an as-completed stream but impossible to get results as fast as possible when the library is holding them hostage for ordering!
69a4934
to
dbad0b2
Compare
Give that new example a shot with |
Still TODO:
|
@richardsheridan i think that get's I'll make a new issue for a more "serious" worker pool recipe to continue the |
c0dbcc5
to
ce61230
Compare
This is a draft of the `tractor` way to implement the example from the "processs pool" in the stdlib's `concurrent.futures` docs: https://docs.python.org/3/library/concurrent.futures.html#processpoolexecutor-example Our runtime is of course slower to startup but once up we of course get the same performance, this confirms that we need to focus some effort not on warm up and teardown times. The mp forkserver method definitely improves startup delay; rolling our own will likely be a good hot spot to play with. What's really nice is our implementation is done in approx 10th the code ;) Also, do we want offer and interface that yields results as they arrive? Relates to #175
ce61230
to
5ffd2d2
Compare
6bba5d9
to
2b3beac
Compare
I'm a little perplexed between the state of this pr and #163 . It seems you made the |
@richardsheridan haven't rebased that PR yet onto this history 😂 This one is just to get the examples in; that one is to document them in the README. |
Yah, |
This is a draft of the
tractor
way to implement the example from the"processs pool" in the stdlib's
concurrent.futures
docs:https://docs.python.org/3/library/concurrent.futures.html#processpoolexecutor-example
Our runtime is of course slower to startup but once up, we get the same performance, this confirms that we need to focus some effort on warm up and teardown times. The mp forkserver method definitely improves startup delay; rolling our own will likely be a good hot spot to play with.
What's really nice is our implementation is done in approx one 10th of the code ;)
Also, do we want offer and interface that yields results as they arrive?
Relates to #175
What y'all think?
Results from running both scripts:
Ours:
stdlib's