Backends
Choose a collector with backend=... or --backend. Trace is the default.
Choose a backend
| Feature | Trace | Scalene | Tachyon |
|---|---|---|---|
| Python versions | 3.11–3.15 | 3.11–3.14 | 3.15 |
| Collection | Tracing | Sampling | External sampling |
| Line and function time | ✓ | ✓ | ✓ |
| Hits, calls, and per-call averages | ✓ | ✗ | ✗ |
| Sample counts | ✗ | ✓ | ✓ |
| Retained Python allocation changes | ✓ | ✓ | ✓ |
| Process RAM and timeline | ✓ | ✓ | ✓ |
| GPU time and memory | ✗ | ✓ | ✗ |
| Library cost attributed to project lines | ✓ | ✓ | ✓ |
| Multiple Python threads | ✗ | ✓ | ✗ |
| Configurable sampling rate | ✗ | ✓ | ✓ |
Enable memory with memory=True; GPU collection requires Scalene and
gpu=True.
Scalene
Install linescope[scalene] and select backend="scalene".
Scalene samples Python threads and attributes library work to the calling
project line. It also supports GPU metrics. Short operations may
receive no samples; exact hit and call counts are unavailable.
Trace
Select backend="trace" for line events and execution counts in the starting
thread. Tracing adds overhead, especially in tight loops, and shares hooks with
debuggers. GPU requests warn and continue without device metrics.
Tachyon
Select backend="tachyon" on Python 3.15 to use profiling.sampling without
an extra dependency. A separate collector samples the starting thread.
Process-access restrictions can prevent attachment. Hit counts and GPU metrics
are unavailable.
Profiling scope
root, include, and exclude select source files. Separate worker processes
are not profiled. A calling line can include the wait for workers; keep their
completion inside the session to measure it. Elapsed time is wall time, not
summed worker CPU time.
Spark profiling covers driver Python. Executors contribute only the metrics Spark exposes.
Performance
Sampling rate
from linescope import profile
with profile(backend="scalene", sample_rate=250):
run_pipeline()
Scalene and Tachyon default to 1000 samples per second. Set sample_rate or
--sample-rate to change the target; Trace ignores it. Higher rates add
overhead. The report shows the achieved rate.
Collection overhead
Memory tracking adds allocation snapshots, RAM reads, and line tracing, even
with sampling. Live notebook reports add work after each cell. Use
display="end" for one report, or display="none" to save it yourself.
Compare runs with the same settings and inputs. Check improvements without the profiler too.
Memory
Enable process RAM and retained Python allocations with memory=True or
--memory. No allocator preload or kernel restart is needed.
from linescope import profile
with profile(memory=True, display="none") as session:
values = [bytearray(1024) for _ in range(10_000)]
session.save("memory.html")
Python allocation changes
memory.delta_bytes compares tracemalloc snapshots and attributes retained
bytes to their allocation site. Freed bytes reduce that site's total.
Allocations freed between snapshots are not counted.
This covers Python threads but excludes untracked native allocations, device memory, and separate processes. Per-line allocation peaks are unavailable. Existing allocation tracing stays running; shallow tracebacks can limit library attribution. If the workload stops tracing, allocation values become unavailable.
RAM readings and growth
Process RAM is RSS, or the working set on Windows. It includes Python objects, native buffers, shared pages, and profiler overhead.
Mem Change accumulates RAM changes during a line's intervals. Peak Mem is its highest observed reading. Other threads can affect both. Brief spikes may be missed, particularly in native calls holding the GIL. Deleting an object may not reduce RAM because allocators retain freed memory.
The Memory view plots readings over time. Long timelines may be compressed; line statistics still use every observation.
Driver and executor memory
Spark driver RAM excludes the JVM and executors. A lazy DataFrame can use
little Python RAM until an action such as toPandas() brings data into it.
Spark memory and spill counters measure other
scopes and should not be added to RAM.
Child processes have separate timelines. Shared source pages keep the largest observed peak, but leave combined Mem Change unavailable.
Custom backends
Implement ProfilerBackend, declare BackendCapabilities, and register a
factory with register_backend. Return RawBackendResult measurements with
None for unavailable values. Release owned resources on failure.