Netatalk provides a containerized profiling workflow that generates interactive SVG flamegraphs of the afpd daemon while running the AFP test suite. This is useful for identifying CPU hotspots, verifying performance optimizations, and understanding code paths exercised by specific test workloads.
The profiling infrastructure uses Linux perf for sampling and Brendan Gregg's FlameGraph tools to produce the visualization.
Build the debug profiling container:
Run the spectest with on-CPU flamegraph profiling:
Open flamegraph.svg in a web browser. The interactive SVG allows clicking to zoom into specific call stacks and hovering to see sample counts.
The debug Dockerfile builds Netatalk with:
The debug entrypoint script wraps the normal test execution with profiling:
The fd-redirect approach (stdout=SVG, stderr=logs) means you capture the SVG cleanly with shell redirection while still seeing test progress on the terminal.
Samples the CPU at a fixed frequency to show where afpd spends its processing time. Best for workloads that exercise complex server-side logic.
Recommended test suites: spectest, lantest
Traces kernel scheduler context switches to show where afpd spends time sleeping or blocked (I/O waits, poll, locks). The resulting flamegraph uses a blue color palette to visually distinguish it from on-CPU flamegraphs.
Recommended test suites: speedtest and other I/O-bound workloads
The following environment variables control the profiling behavior. They are used in addition to the standard container environment variables documented in CONTAINERS.md.
| Variable | Description |
|---|---|
| FLAMEGRAPH | Set to any value to enable profiling |
| FLAMEGRAPH_OFFCPU | Set to any value to use off-CPU mode |
| PERF_FREQ | On-CPU sampling frequency in Hz (default: 999) |
Produces the richest flamegraphs. The spectest exercises hundreds of distinct AFP protocol operations including directory traversal, file creation, metadata manipulation, authentication, volume enumeration, and resource fork handling. The resulting flamegraph shows a broad cross-section of afpd code paths.
Exercises read/write/copy operations with protocol-level verification. Produces good flamegraphs at the default 999 Hz sampling rate showing the AFP command dispatch, DSI framing, and file I/O paths.
Over loopback, the speedtest is I/O-bound — afpd spends most of its wall time sleeping in poll() waiting for the next request. On-CPU flamegraphs show minimal data because the DSI layer processes each request in microseconds. Use off-CPU mode (FLAMEGRAPH_OFFCPU=1) to see where afpd blocks, or run against a remote host with real network latency for meaningful on-CPU data.
| File | Purpose |
|---|---|
| distrib/docker/debug_alp.Dockerfile | Alpine debug build with perf |
| distrib/docker/debug_entrypoint_netatalk.sh | Entrypoint with profiling support |
Look for wide frames near the top of the stacks — these are the functions where afpd spends the most CPU time. Narrow frames deep in the stack show the call path that led there.
See Brendan Gregg's Flame Graphs page for a comprehensive guide to reading and interpreting flamegraphs.