DYLD_INSERT_LIBRARIES environment variable.
System Integrity Protection (SIP)
strips all DYLD_* environment variables whenever a protected Apple system
binary is executed, e.g., /bin/sh, /usr/bin/env, the system
/usr/bin/python3, or the built-in coreutils. Once such a binary is executed,
the profiling library is removed from that process and every process it spawns.
The entire subtree becomes invisible to the profiler.
What this looks like
In the following execution tree, π marks a profiled process and π marks a SIP-protected system binary. Processes without an icon are not profiled:Execution tree
node_modules/.bin shims go through /usr/bin/env and /bin/sh, so the
profiling variable is stripped several times along the chain:
Execution tree (pnpm run bench)
CodSpeed re-sets
DYLD_INSERT_LIBRARIES when launching benchmark runtimes
such as Node.js and Go, re-enabling profiling for the rest of the process
tree. Only the SIP-protected system processes themselves are never profiled.When to ignore the warning
Check which binaries the warning mentions:- If they are launchers like
/bin/shor/usr/bin/envand your flamegraph contains your benchmark code, ignore the warning. The launcher only accounts for a negligible amount of time. - If the work you want to profile happens inside a system binary itself, e.g.,
you benchmark the system
/usr/bin/python3, use one of the workarounds below.
Workarounds
Use a non-system toolchain
The recommended fix is to make sure no SIP-protected binary appears in the benchmarkβs process tree. This requires no system changes and is the only workaround that also applies in CI. SIP only protects the binaries that ship with macOS, under/usr/bin, /bin,
/usr/sbin, and /sbin. Toolchains installed by a package manager, e.g.,
Homebrew, uv, pyenv, nvm, or rustup, live outside these paths and are
profiled normally:
- Install the toolchain with a package manager instead of using the system one
under
/usr/bin. - Invoke it directly, so the kernel never executes a protected binary, e.g.,
uv run python3 bench.pyinstead ofpython3 bench.py.
Disable SIP
For local profiling on a machine you control, you can disable the part of SIP that stripsDYLD_* variables. With it disabled, system binaries are profiled
like any other process.
Follow
Appleβs instructions for disabling System Integrity Protection:
boot into Recovery Mode, run one of the following commands in the Terminal, and
reboot:
DYLD_* variables, so disabling only them keeps the filesystem and
kernel extension protections in place.
To re-enable SIP when you are done, boot into Recovery Mode again and run:
csrutil status.
Profiling in CI
SIP cannot be disabled on CI-hosted macOS runners, e.g., GitHub-hosted macOS runners. The only available workaround is to use a non-system toolchain: point the benchmark command at the exact non-system toolchain binary and avoidenv or shell shims
where possible.
System processes will not appear in CI profiles, and that is expected. It does
not affect the correctness of the benchmark measurements for your own code.
Next Steps
Walltime Instrument
Learn how the walltime instrument measures real-world execution time
Profiling
Learn how to read flamegraphs and use profiling data to optimize your code