Live code profiling provides a breakdown of the most frequent functions and methods in a transaction. The level of detail varies by language, but typically includes information down to the class, method, and even filename and line number. It provides enough detail to understand what line of code is causing a performance issue, and includes the information needed to quickly find the relevant section in the source code.
This works by automatically collecting statistical profiling data (which we call snapshots) associated with a transaction, where the agent takes stack traces at a set interval as the transaction is processed. On finish, the reported snapshots are analyzed to build a tree of call paths for the corresponding trace, which shows the frequency of occurrence of each frame in that path.
The interval at which the agent takes stack traces can be changed. The shorter the interval, the more accurate the call paths will be. However, a short interval also affects application performance and generates more data which increases bandwidth usage, so intervals shorter than the default 20ms (supported by some agents) should be used with caution.
Traces with duration shorter than the profiling interval might not have profiling information.
Code profiling is disabled by default. See the links below to enable it in the supported agents:
Once enabled, if a trace resulted in profiling information, you can see it by going to the Trace Details view, then clicking on a span (most likely you’d want to click the root span) to open the detail window on the right. If there is profiling information for the selected span, there will be a Code Profile tab that displays the tree of call paths and frequencies:
The tree is a parent-to-child view of the call paths built from stack traces reported in the profiling snapshots, where the bottom path segment (i.e. tip or leaf node) of each branch is the frame in execution at the time the snapshot was taken. You’ll find the following in each path segment:
Percentage – the frequency with which this frame occurred in the call path, as a percentage of all profiling snapshots collected for this trace. Thus the percentage will decrease as you traverse down a branch from the parent frame (which is found in all snapshots) to the frame in execution (found in a subset of the snapshots).
Function / File / Line Number(s) – each frame has one or more of these elements that identify the code in execution, please note there are language-specific variations in whether all pieces are available. The format is:
function or method name (file name): line number
When a function occurs in the same call path but on different line numbers, these are merged together for the percentage calculation and shown as a single path segment, with multiple comma-separated line numbers.
By default, the displayed tree collapses sequential path segments that have the same percentage, to better reveal possible bottlenecks in the code. You can use the “arrow” icon on the left of each segment to toggle this, and the Zoom In link above the tree to expand the Code Profile window.
In most cases the statistical profiling approach of taking snapshots on interval allows the agent to be performant while giving a good representation of the proportion of time being spent in different parts of the code. The trade-off is that short traces where only a few snapshots are collected will lose accuracy.