4.1 KiB
Raw AI output — gh #470 import tractor latency trim
All generated code is committed on the wkt/boot_latency_470 branch; per diff-ref mode each file’s content is referenced via its diff instead of copied verbatim.
Profiling findings (verbatim analysis output)
Baseline: import tractor ~0.39-0.42s wall.
python -X importtime + cProfile traced the cost NOT primarily to third-party deps (the issue’s hypothesis) but to tractor/log.py:get_logger() calling get_caller_mod() -> inspect.stack() at module level in ~39 tractor modules:
inspect.stack()buildsFrameInfo(incl. src-file and line-context resolution) for EVERY frame on the stack; during nested imports the stack is dozens of importlib frames deep.- each
FrameInforesolution callsinspect.getmodule()which scans all ofsys.modulesper frame (1.4Mismodule()calls in one profiled import). - aggregate: ~244ms of tractor-own module “self” time vs ~20ms for ALL the issue-listed third-party deps (
pdbp~10ms,bidict~4.5ms,multiaddr~3.5ms,wrapt/colorlog~1ms each);trioitself is ~70-100ms and unavoidable.
Generated changes
git diff main..wkt/boot_latency_470 -- tractor/log.py
get_caller_mod() rewritten from inspect.stack() + inspect.getmodule() to sys._getframe(frames_up) + frame.f_globals['__name__'] -> sys.modules lookup (O(1) vs O(stack x sys.modules)). Unused inspect imports dropped; FrameType imported from types. Also colorlog lazy-imported inside get_console_log().
git diff main..wkt/boot_latency_470 -- tractor/discovery/_addr.py
bidict import moved under TYPE_CHECKING (annotation-only use; _address_types is a plain dict literal).
git diff main..wkt/boot_latency_470 -- tractor/discovery/_multiaddr.py
from __future__ import annotations added; multiaddr import moved under TYPE_CHECKING + function-local imports in mk_maddr()/parse_maddr().
git diff main..wkt/boot_latency_470 -- tractor/ipc/_tcp.py tractor/ipc/_uds.py
Multiaddr imports moved under TYPE_CHECKING (annotation-only in both transports).
git diff main..wkt/boot_latency_470 -- tractor/runtime/_state.py
platformdirs lazy-imported inside get_rt_dir() (NOTE: still imported eagerly via UDSAddress.def_bindspace class-var eval; see follow-ups).
git diff main..wkt/boot_latency_470 -- tractor/devx/_frame_stack.py
pdbp + wrapt lazy-imported inside hide_runtime_frames() / api_frame() respectively.
git diff main..wkt/boot_latency_470 -- tractor/devx/debug/_trace.py tractor/devx/debug/_tty_lock.py
asyncio moved to TYPE_CHECKING + call-site local imports (asyncio.current_task() sites); tractor.to_asyncio.run_trio_task_in_future imports moved into the infected-aio runtime branches.
git diff main..wkt/boot_latency_470 -- tractor/spawn/_entry.py
run_as_asyncio_guest import moved into the infect_asyncio=True branches of _mp_main() / _trio_main().
git diff main..wkt/boot_latency_470 -- tractor/__init__.py
PEP 562 module __getattr__ added so tractor.to_asyncio attr-access still works (required by tests/test_child_manages_service_nursery.py and any downstream user) while keeping asyncio off the eager import path.
Measured results (verbatim)
import tractor: 0.39-0.42s -> ~0.145s (~65% cut)start_actorspawn+boot+reg+cancel: ~0.40-0.44s -> ~0.179s/actor (n=5 sequential, warm parent)- post-change eager-module check: only
pdbp+platformdirsof the issue’s list remain eager.
Known follow-ups (not implemented, deadline-bound)
pdbp(~10ms): still eager viadevx/debug/_repl.pyclass bases (class PdbREPL(pdbp.Pdb)) +_tty_lock.pymodule-level@pdbp.hideframe; needs_replrestructure + PEP 562 indevx.debug.__init__.platformdirs(~1.5ms): eager viaUDSAddress.def_bindspace: ClassVar = get_rt_dir()class-body call; needsAddress-protocol rework ofdef_bindspaceto a lazy accessor.stackscope+setproctitle: already lazy/absent — no change needed.