Measuring function runtimes

Updated: October 26, 2022

You can instrument an application binary to report timestamps of function entrances and exits. The Application Profiler can then measure and report the total time spent in each function, allowing you to monitor execution time breakdown based on the application's workflow (i.e., action sequence).

This profiling method has more overhead than sampling execution positions but doesn't require you to gather a statistically significant number of samples, meaning it works on short- or long-running programs. It performs better on one thread because with many threads, the measurement overhead can change the application's behavior.

To profile functions, your source files must be compiled with -finstrument-functions and your binaries linked with -lprofilingS; for details, see Enabling function instrumentation.

Note: You can run an application with profiling instrumentation from the command line. However, using the IDE is more convenient because the Application Profiler automates the requesting of data from the instrumented binary and presents the results in an easy-to-read format.
To profile an application by measuring function runtimes:
  1. In the launch bar, expand the Launch Configuration dropdown (which is in the middle) and select the project that you want to profile.
  2. In the Launch Target dropdown (on the right), select the target for running your application.
  3. In the Launch Mode dropdown (on the left), select Profile.
  4. Click the Edit button (Icon: Edit button) on the right of the Launch Configuration dropdown.
  5. In the configuration editor window, click the Profile tab on the right and the Application Profiler radio button near the top of this tab.
  6. Ensure that Functions Instrumentation is selected under Profiling Method and Single Application is selected under Profiling Scope.
  7. Optional: You can customize how the profiling tool behaves through the Options and Control panels.
    For details about these fields, see the Application Profiler reference.
  8. Click OK to save the configuration changes and close the window.
  9. In the launch bar, click the Profile button (Icon: Profile button).

The IDE switches to the QNX Analysis perspective. If necessary, the IDE first builds the binary. Then, it uploads the binary and starts running it on the target. At this time, a new session is created and displayed in the Analysis Sessions view. As the application runs, profiling results are sent to the IDE, which stores them in the new session and presents them in the Execution Time view.

The profiling results include the function runtimes, call counts, and call sites. Initially, function information for all program components is listed. You can expand the Analysis Sessions entry and click a component to filter the display. For example, you may want to see only those runtimes for functions in your program code and not in any libraries that it uses, so you can click the application binary.

By default, the Execution Time view shows the threads tree, but for single-threaded applications, it's better to click the Show Table button (Icon: Show Table) in the upper right corner to list the functions in a table:

Screenshot of Execution Time view showing precise deep and shallow function runtimes in a thread-based tree

You should be able to see statistics for functions in any shared libraries used by your application. If you don't, you must manually define the library paths.

One key point in using function instrumentation is that deep and shallow times have distinct meanings. Deep time is the time spent in a function's own code and in the code of any functions that it calls. Shallow time is the time spent in a function's code and inside any functions that it calls but aren't instrumented themselves. Generally, this is all of the QNX library. Note that shallow time can't be computed for functions still executing. You can change the columns displayed to see nondefault metrics, as explained in the Execution Time reference.

Like the System Information statistics, the profiling results are refreshed every five seconds (by default), so you can closely monitor changes in execution time breakdown as you interact with the application. Double-clicking on any listing with a file and line number shown in the Location column opens the source code at that location. The IDE displays a bar graph and the execution time in the left margin.

Note: You can concurrently profile as many applications as you like and multiple instances of the same application. The results for each execution run appear in their own Application Profiler session, independently of other sessions.