Profiling
CHIA can profile a loop’s execution (how long each ChiaFunction call
took, which worker ran it, and how calls depend on one another) and render the
result as a dependency graph, an interactive timeline, or a CSV table. Profiling
is built around ChiaProfiler, a singleton that instruments every
ChiaFunction call automatically once a collector is running.
Start the collector on the driver, run your loop, then point the ``chia viz-profile`` CLI at the JSONL log it wrote.
Enabling profiling
Start the ChiaProfileCollector from the driver, after ray.init() and before any
profiled @ChiaFunction calls:
import ray
from chia.trace.profiler import start_collector
ray.init(address="auto")
# Defaults to logging under /tmp/ray/{job_id}.
start_collector(log_dir="/data/chia_profiles")
# ... run your @ChiaFunction loop ...
The ChiaProfileCollector is cleaned up automatically on ray.shutdown() or process exit; you
can also stop it explicitly:
from chia.trace.profiler import stop_collector
stop_collector() # idempotent
What gets recorded
Once the collector is running, ChiaFunction instruments itself with no
changes to your code. Every call emits events keyed by a globally unique
call_id:
dispatch— a remote call (chia_remote()) started on a worker. Carries the worker IP / id, node id, Rayresources, andobj_ref_deps(the dependency edges, see below).complete— a remote call’s result was retrieved viaget(). Carriesexec_time_s(high-resolution execution time) plus anyadd_infometadata.local_start/local_end— aChiaFunctionthat ran locally rather than on a worker.local_endalso carriesexec_time_s.
Dependency edges
The profiler reconstructs the task graph by tracking object identity: when a call
returns a value, it records id(value) -> call_id; when a later call receives
that same object as an argument, it emits a dependency edge (obj_ref_deps).
Small interned values (int, float, str, bytes, bool,
None) are deliberately skipped to avoid false-positive edges.
Attaching custom metadata
From inside any @ChiaFunction body, call add_info to merge extra fields
into that call’s complete (or local_end) event. It is thread-local, so
concurrent tasks don’t cross metadata:
from chia.trace.profiler import get_profiler
@ChiaFunction
def run_verilator_test(design):
cycles = ... # run the sim
get_profiler().add_info({"simulation_cycles": cycles})
return result
This is how CHIA’s library nodes surface domain metrics — e.g. simulation cycles
and waveform sizes from Verilator runs, or token counts and cost from LLM model
calls — into the profile. The metadata lands under the event’s extra key.
For events that aren’t tied to a single call, use log_event:
get_profiler().log_event("checkpoint", iteration=3, note="post-merge")
Each custom event is timestamped and tagged with the current worker_id
automatically.
Visualizing a profile
Render a recorded log with the chia viz-profile CLI — a dependency graph
(svg/png/pdf), an interactive HTML timeline, or an aggregated CSV
table. See chia viz-profile <log...> in the CLI Reference for the full list of
formats and flags.