Profiling
The following functions control a profiler attached to the running server. The functions let a policy or a trigger choose which part of a run the profiler measures, instead of measuring from process start to process exit.
The functions for a profiler are only available when the server was built on a system with the development headers for that profiler installed. The runtime-valgrind and runtime-gperftools feature flags report whether the profiler is attached. The server prints the feature flags at startup when run with -x. A call to a function whose profiler is not attached fails the expansion and logs the reason.
This page uses the terms of each profiler. Callgrind counts costs (instruction fetches, cache misses, branch mispredictions) into one cost centre per function, and writes the cost centres as a profile dump. gperftools records samples of the program counter on a timer, and writes the samples to a profile file.
The usual way to use these functions is from the server.start and server.stop triggers. The server.start trigger fires once the worker threads are running. The server.stop trigger fires after the server receives a request to exit. The -S option sets a trigger from the command line without editing the configuration:
radiusd -f -S 'trigger.server.start=%callgrind.start()' -S 'trigger.server.stop=%callgrind.stop()'
Callgrind
Callgrind is the call graph profiler in valgrind. Start the server with instrumentation switched off, so that callgrind does not profile configuration parsing and module loading. Then switch instrumentation on from a trigger:
valgrind --tool=callgrind --instr-atstart=no \
radiusd -f -S 'trigger.server.start=%callgrind.start()'
Instrumentation is process-wide, so the thread that runs the function does not matter.
%callgrind.start()
Switch callgrind instrumentation on. When cache simulation is enabled, callgrind flushes the simulated cache, so the first moments after the call show an artificial burst of cache misses.
Use this function when the profile should begin later than process start. The server.start trigger is the usual place to call this function, because configuration parsing and module loading have finished when the trigger fires.
%callgrind.stop()
Switch callgrind instrumentation off. Callgrind keeps the costs already collected, and writes the costs when the process exits or when %callgrind.dump() runs.
Use this function when the profile should end before process exit. A call from the server.stop trigger keeps thread teardown out of the profile. A call from a policy ends the profile after a chosen section of unlang.
%callgrind.dump([<label>])
Write the costs collected so far to a new profile dump, then zero the costs. Callgrind records the optional label in the dump, so the reader can distinguish the dumps when one run produces several.
Use this function when one run should produce several profile dumps, such as one dump per load step, or one dump for the load phase and one dump for shutdown. Instrumentation stays on, and each dump holds only the costs counted since the previous dump. callgrind_annotate accepts several dumps at once.
%callgrind.dump('load complete')
%callgrind.zero()
Zero the costs collected so far without writing a dump.
Use this function to discard the costs of a period that the profile should not include. Examples are the cache warmup after %callgrind.start(), and a settling period after a load step changes the request rate. Call this function when the period ends. The next profile dump, or the dump at process exit, then holds only the costs counted after the call.
gperftools
The gperftools CPU profiler samples the program counter on a timer and writes the samples to a file for pprof to read. The profiler runs at close to native speed, so use the profiler to measure real timing. The profiler does not count instructions or simulate caches.
%gperftools.start(<filename>)
Start the profiler, writing samples to filename. The function fails if the profiler is already running, so a second start never discards a running profile. The limit files { … } section restricts the filename in the same way as for the file handling functions.
Use this function to measure where the server spends wall-clock time. The server.start trigger is the usual place to call this function.
radiusd -f -S 'trigger.server.start=%gperftools.start("/var/log/radius/cpu.prof")' \
-S 'trigger.server.stop=%gperftools.stop()'
%gperftools.stop()
Write any buffered samples to the profile file, then stop the profiler. The function fails if the profiler is not running.
Use this function to end the profile at a known point, usually from the server.stop trigger. %gperftools.start() starts a stopped profiler again with a new profile file.
%gperftools.flush()
Write any buffered samples to the profile file and keep the profiler running. The function fails if the profiler is not running.
Use this function during a long run, so that pprof can read a partial profile while the server keeps running. Also use this function before a step that might crash the server. The buffered samples then reach the profile file before the crash.