--- model: claude-fable-5 service: claude timestamp: 2026-07-02T15:56:26Z git_ref: 65bf9df5 diff_cmd: git diff main..wkt/boot_latency_470 --- # 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()` builds `FrameInfo` (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 `FrameInfo` resolution calls `inspect.getmodule()` which scans all of `sys.modules` per frame (1.4M `ismodule()` 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); `trio` itself 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_actor` spawn+boot+reg+cancel: ~0.40-0.44s -> ~0.179s/actor (n=5 sequential, warm parent) - post-change eager-module check: only `pdbp` + `platformdirs` of the issue's list remain eager. ## Known follow-ups (not implemented, deadline-bound) - `pdbp` (~10ms): still eager via `devx/debug/_repl.py` class bases (`class PdbREPL(pdbp.Pdb)`) + `_tty_lock.py` module-level `@pdbp.hideframe`; needs `_repl` restructure + PEP 562 in `devx.debug.__init__`. - `platformdirs` (~1.5ms): eager via `UDSAddress.def_bindspace: ClassVar = get_rt_dir()` class-body call; needs `Address`-protocol rework of `def_bindspace` to a lazy accessor. - `stackscope` + `setproctitle`: already lazy/absent — no change needed.