callsight — compile-time function tracing for C/C++
Docs: https://harshithsunku.github.io/callsight/ · Status & roadmap
Add entry/exit timing hooks to every function in a C/C++ project at compile time, with zero edits to its sources, control exactly which files, folders, or functions get hooks from one config file, and turn the resulting traces into per-function hotspot reports. Works with GCC and Clang, C and C++, with GNU Make and CMake projects.
Install
uv tool install callsight # from PyPI; puts `callsight` on your PATH
uv tool install 'callsight[ui]' # same, plus the optional web UI
uv tool install . # or from a source checkout
(Requires uv. The tool itself is Python stdlib-only; the runtime it injects is dependency-free C.)
Web UI
callsight ui # serves http://127.0.0.1:8321
A local web app that walks the whole workflow against any project on the
machine: browse for the project folder, edit its trace.config, preview
the instrumentation selection, build the instrumented profile (Make or
CMake — CMake is fetched ephemerally via uvx if not installed), run the
binary with tracing enabled, and view the sortable hotspot report. No root
needed; bind address defaults to localhost.
Adopt it in your project (2 steps)
cd /path/to/your/project
callsight init . # copies runtime + build wiring, writes trace.config
Then follow the printed wiring snippet for your build system:
- Make:
include callsight/Makefile.callsight, add aninstrumenttarget linking$(TRACE_OBJ)with-no-pie(snippet printed byinit). - CMake:
include(CallSight)+callsight_instrument(<target>), then configure with-DCALLSIGHT_INSTRUMENT=ON.
Collect and analyze
make instrument # or: cmake --build build-instr
TRACE_ENABLE=1 TRACE_MAX=1000000 ./yourapp # collect (inert without TRACE_ENABLE=1)
callsight analyze traces/ --exe ./yourapp --top 20
The analyzer reports calls / inclusive / self / max time per function,
resolving symbols — including static functions — with addr2line.
unmatched_exits=0 means a clean trace.
How it works
callsight flagsturnstrace.config+ your source list into-finstrument-functionsplus compile-time exclude lists (-finstrument-functions-exclude-file-list/-exclude-function-list).- The compiler emits calls to
__cyg_profile_func_enter/exitat the entry/exit of every selected function. Excluded code emits no hook at all — compile-time exclusion is free at runtime. - The hook runtime (
trace.c, itself compiled without the flag) appends 32-byte events to a per-thread buffer — no locks, no malloc, no I/O in the hot path — flushingtrace.<pid>.<tid>.binwhen full or at exit. callsight analyzematches enter/exit events per thread and prints hotspot tables.
Selection strategy (important at scale)
Event volume is the main cost — a call-heavy program easily generates millions of events per second. Levers, cheapest first:
- Compile-time excludes in
trace.config: run wide once, sort analyzer output bycalls, exclude the chatty leaf helpers, rebuild. Typically cuts volume 10–100×. includedirectives: instrument only the subsystem under investigation.include-func(function/task level): name one entry function and callsight instruments exactly its call subtree, resolved statically from the sources —include-func workload_sorttracesworkload_sortand everything it calls, nothing else. Explore first withcallsight select src/ --function workload_sort.- Runtime gating:
TRACE_ENABLE/TRACE_MAXcontrol when and how much you pay;TRACE_THREADS="sort-*"traces only matching threads. - Source opt-out (optional):
__attribute__((no_instrument_function)).
callsight scan <dir> --config trace.config previews what a config selects.
Runtime knobs: TRACE_ENABLE (default off), TRACE_DIR (default
./traces), TRACE_MAX (global event cap — always set one for long runs),
TRACE_THREADS (thread-name glob filter), TRACE_SHM / TRACE_SHM_SIZE
(streaming mode, see below).
Remote streaming (devices, embedded)
On a constrained device you can't accumulate trace files — a busy program generates millions of events per second. Streaming mode keeps nothing on the device: the runtime flushes into a shared-memory ring, and a tiny on-device client forwards events ZSTD-compressed over raw TCP.
# analysis host (powerful machine):
callsight serve --port 9001 --out traces/ # needs callsight[stream]
# adopt with streaming support:
callsight init --stream /path/to/project # adds trace_stream.c + zstd.c
# on the device:
cc -O2 -o callsight/trace_stream callsight/trace_stream.c callsight/zstd.c
./callsight/trace_stream /callsight0 <server-ip> 9001 &
TRACE_ENABLE=1 TRACE_SHM=/callsight0 ./yourapp.instr
- The traced process does no disk or network I/O — only a shared-memory memcpy per buffered batch.
- If the ring fills faster than the client drains (network slow, ring too
small), events are dropped and counted, never blocking the workload;
the server reports the drop count. Size the ring with
TRACE_SHM_SIZE. - The server writes standard
trace.stream.*.binfiles —callsight analyzeand the web UI consume them unchanged. - The client is self-contained C built against the vendored single-file
zstd v1.5.7 (
src/callsight/stream/zstd.c, generated from the official repo'sbuild/single_file_libs; BSD license inzstd.LICENSE).
CLI reference
| command | purpose |
|---|---|
callsight init <dir> [--build make|cmake] |
adopt into a project |
callsight scan <dir> [--config c] |
preview instrumentation selection |
callsight select <dir> --function F [--depth N] |
show a function's call subtree; emit config lines |
callsight flags --config c -- srcs... |
print compiler flags (build integrations use this) |
callsight analyze [traces/] [--exe bin] [--top N] |
hotspot report |
callsight ui [--host H] [--port P] |
web UI (needs callsight[ui]) |
callsight serve [--host H] [--port P] [--out dir] |
TCP server for remote streams (needs callsight[stream]) |
Repo layout
src/callsight/— the tool:cli.py,flags.py(config → compiler flags),analyze.py(offline analyzer); stdlib-only.src/callsight/ui/is the optional web UI (FastAPI, only imported bycallsight ui).src/callsight/runtime/—trace.c/trace.h/trace_shm.h, the hook runtime copied into adopted projects. Self-contained C, no deps beyond pthreads.src/callsight/stream/—trace_stream.con-device streaming client + vendored single-file zstd v1.5.7 (zstd.c, BSD — seezstd.LICENSE).src/callsight/share/Makefile.callsight,src/callsight/cmake/CallSight.cmake— build-system integrations.tests/matrixlab/— multi-threaded C11 demo workload; doubles as the end-to-end smoke test (make instrument→ run →callsight analyze).tests/cmake_demo/— tiny CMake fixture for the CMake integration.docs/instrumentation-options.md— survey of GCC/Clang compile-time instrumentation mechanisms and how they map to callsight's roadmap.
Known limitations
- Inlined functions emit no hooks (there is no call boundary).
- Overhead ~30–60 ns per event; a profiling build, not a production one.
- A crashed/killed process loses each thread's buffered tail; clean exits flush everything.
exclude-file-listmatching by the compiler is substring-based; unusually overlapping directory names can over-match.
Roadmap
- Phase 2 — web UI: done (
callsight ui, optionalcallsight[ui]extra). Next: richer report views (call graphs, flame graphs), live build-log streaming. - Phase 3 — remote streaming: done (
TRACE_SHMring →trace_streamclient → ZSTD/TCP →callsight serve). Next: runtime on/off via-fpatchable-function-entry(see docs/instrumentation-options.md), live stream view in the web UI.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file callsight-0.1.0.tar.gz.
File metadata
- Download URL: callsight-0.1.0.tar.gz
- Upload date:
- Size: 5.3 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7078b44c0e5fde2d01a5d22de6aa3cd10f42bff8eb16151272332057b25cf277
|
|
| MD5 |
702c3d108d1f57f7642d32ceb3724ece
|
|
| BLAKE2b-256 |
de94a2f3723445c449ab044de1e5ff1e94498b861331a47d4c13b1e193be6f84
|
Provenance
The following attestation bundles were made for callsight-0.1.0.tar.gz:
Publisher:
release.yml on harshithsunku/callsight
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
callsight-0.1.0.tar.gz -
Subject digest:
7078b44c0e5fde2d01a5d22de6aa3cd10f42bff8eb16151272332057b25cf277 - Sigstore transparency entry: 2460855908
- Sigstore integration time:
-
Permalink:
harshithsunku/callsight@bba1a9aada3f7b242d787731cf9eacd397b0f3ac -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/harshithsunku
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@bba1a9aada3f7b242d787731cf9eacd397b0f3ac -
Trigger Event:
push
-
Statement type:
File details
Details for the file callsight-0.1.0-py3-none-any.whl.
File metadata
- Download URL: callsight-0.1.0-py3-none-any.whl
- Upload date:
- Size: 569.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f3620ef54983dab11a61940d04f593411e8dddec0ea4e4b43d05294ae702829c
|
|
| MD5 |
f0db49ba8dc83e86303648fb739ee9ed
|
|
| BLAKE2b-256 |
b6be1308498b3a68778bca470064dcf3ba2ea1c392dfc4214155701ed7d16b00
|
Provenance
The following attestation bundles were made for callsight-0.1.0-py3-none-any.whl:
Publisher:
release.yml on harshithsunku/callsight
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
callsight-0.1.0-py3-none-any.whl -
Subject digest:
f3620ef54983dab11a61940d04f593411e8dddec0ea4e4b43d05294ae702829c - Sigstore transparency entry: 2460856513
- Sigstore integration time:
-
Permalink:
harshithsunku/callsight@bba1a9aada3f7b242d787731cf9eacd397b0f3ac -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/harshithsunku
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@bba1a9aada3f7b242d787731cf9eacd397b0f3ac -
Trigger Event:
push
-
Statement type: