Make sub-spawn strategy toggleable in `we_are_processes`
The #470 boot-latency example hard-coded spawning each `worker_<i>` subactor concurrently from a bg `trio.Task` (so each child's cold `import tractor` overlaps). Add a `main()` `spawn_subs_in_bg_tasks` flag so the serial-spawn path can be demo'd/compared too: flip it `False` to `start_actor()` each sub inline in the loop before handing the ready `Portal` to the bg task. Deats, - factor an `open_ep(ptl, i)` helper out of `spawn_and_open_ep()` - just the `Portal.open_context()` + `wait_for_result()` half, now that the spawn step is caller-optional. - `spawn_and_open_ep()` grows a `maybe_ptl: Portal|None = None` param: spawn the subactor itself when unset (bg-task path), OW reuse the pre-spawned one (serial path). - move the "overlap cold imports" rationale comment onto the new `main()` param where the toggle now lives. (this commit msg was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-codeboot_latency_470
parent
7f98a5801e
commit
95a2b18267
|
|
@ -23,18 +23,10 @@ async def endpoint(
|
|||
await trio.sleep_forever()
|
||||
|
||||
|
||||
async def spawn_and_open_ep(
|
||||
an: tractor.ActorNursery,
|
||||
async def open_ep(
|
||||
ptl: tractor.Portal,
|
||||
i: int,
|
||||
) -> None:
|
||||
'''
|
||||
Spawn a subactor, start a remote `endpoint()`-task in it.
|
||||
|
||||
'''
|
||||
ptl: tractor.Portal = await an.start_actor(
|
||||
name=f'worker_{i}',
|
||||
enable_modules=[__name__],
|
||||
)
|
||||
ctx: tractor.Context
|
||||
async with ptl.open_context(endpoint) as (
|
||||
ctx,
|
||||
|
|
@ -47,7 +39,33 @@ async def spawn_and_open_ep(
|
|||
await ctx.wait_for_result()
|
||||
|
||||
|
||||
async def main():
|
||||
async def spawn_and_open_ep(
|
||||
an: tractor.ActorNursery,
|
||||
i: int,
|
||||
maybe_ptl: tractor.Portal|None = None,
|
||||
) -> None:
|
||||
'''
|
||||
Spawn a subactor, start a remote `endpoint()`-task in it.
|
||||
|
||||
'''
|
||||
if maybe_ptl is None:
|
||||
maybe_ptl: tractor.Portal = await an.start_actor(
|
||||
name=f'worker_{i}',
|
||||
enable_modules=[__name__],
|
||||
)
|
||||
await open_ep(
|
||||
ptl=maybe_ptl,
|
||||
i=i,
|
||||
)
|
||||
|
||||
|
||||
async def main(
|
||||
# spawn subs concurrently (in bg `trio.Task`s) so each
|
||||
# actor's cold `import tractor` (~0.4s, see #470) overlaps
|
||||
# instead of stacking; once forkserver (#463) lands, spawn
|
||||
# is cheap enough to just loop sequentially.
|
||||
spawn_subs_in_bg_tasks: bool = True,
|
||||
):
|
||||
'''
|
||||
Spawn a subactor-per-CPU then self-destruct the cluster.
|
||||
|
||||
|
|
@ -60,17 +78,21 @@ async def main():
|
|||
# https://github.com/goodboy/tractor/pull/463
|
||||
# start_method='main_thread_forkserver',
|
||||
) as an,
|
||||
# spawn subs concurrently (in bg `trio.Task`s) so each
|
||||
# actor's cold `import tractor` (~0.4s, see #470) overlaps
|
||||
# instead of stacking; once forkserver (#463) lands, spawn
|
||||
# is cheap enough to just loop sequentially.
|
||||
trio.open_nursery() as tn,
|
||||
):
|
||||
for i in range(cpu_count()):
|
||||
|
||||
maybe_ptl: tractor.Portal|None = None
|
||||
if not spawn_subs_in_bg_tasks:
|
||||
maybe_ptl: tractor.Portal = await an.start_actor(
|
||||
name=f'worker_{i}',
|
||||
enable_modules=[__name__],
|
||||
)
|
||||
tn.start_soon(
|
||||
spawn_and_open_ep,
|
||||
an,
|
||||
i,
|
||||
maybe_ptl,
|
||||
)
|
||||
destruct_in: int = 2
|
||||
print(
|
||||
|
|
|
|||
Loading…
Reference in New Issue