The Saturn Back-end

The Saturn back-end is a dynamic library that is linked with the application under study. It is invoked by your application during function prologues and epilogues in order to produce the profile traces used by the Saturn front-end application.

After the back-end is linked with your application, it will automatically produce one or more Saturn profile files in the active each time your application is executed. The output file name format is: “{app name}.{thread #}.sat”. Because each execution of your application can create many different profile files, one for each thread, Saturn creates a new directory in your working directory and names it “Saturn_profile_{app name}_{run number}” to collect all of the separate profiles together. In this name, the run number starts at 0 and is incremented each time you run your program, if you take several profiles in succession.

Most of the time, this library will work for you with very little intervention. However, in case of problems or if you desire more precise control over your profiling then you may need to control it more directly. This chapter discusses some issues that may occur when linking the back-end to your application and some ways that you can control the back-end to get more control over how it profiles your application.

Linking the Back-end to Your Application

As mentioned in the Overview, there are two ways to use the back-end to generate the data files for the front-end:

So which option should you use? In general, the -finstrument-functions option is the better choice. While it can incur somewhat more overhead than the -pg one, it allows Saturn to record more types of information. To be precise, it captures more callstack timing information, which allows Saturn to display its full callstack graph. Without this information, Saturn can present only summary statistics. Moreover, if you are on an Intel-based Mac, this is the only option that you can use.

Environment Variable Controls

If you link with the Saturn dynamic library, you can set the following environment variables in your shell, before starting your application, in order to easily control several options:

Programmatic Start/Stop Control

By default, Saturn profiles your entire application, from beginning to end, in all threads of execution. However, in real programs you often only want to profile a subset of your application’s execution at any one time, in order to focus your analysis on one part of the application or another. To allow you to exercise this level of control, the Saturn back-end contains three other functions that you can use directly in your programs: initSaturn(), startSaturn(), and stopSaturn(). These functions control generation of output data in the back-end dynamic library, enabling profiling for a thread at each startSaturn() call and disabling it at each stopSaturn() call.

Normally, these functions are used in a fairly simple pattern. To explicitly initialize the Saturn back-end for tracing your program, add the call: initSaturn(char *path). This acts much like the automatic initialization, but allows you to explicitly specify the name of your Saturn profile. Once tracing has been initialized, you can then start and stop tracing using pairs of startSaturn and stopSaturn calls.

If your program creates any child threads over the course of its execution, they inherit the profiling status of their parent, by default. Hence these explicit start and stop calls are also a good way to limit profiling to a limited number of threads of interest in a heavily multithreaded program.

API Reference

This section gives a brief reference for the three routines you can use to control Saturn directly.

  • initSaturn

    void initSaturn(char *path);

    This must be called before any startSaturn or stopSaturn calls are made. It initializes Saturn with the following parameter:

    path— The path of the directory to write output files. This can be a full path or a path relative to the current working directory. A NULL or an empty string argument will cause the files to be written in the current working directory.

  • startSaturn

    void startSaturn(void);

    Begins Saturn profiling. Data for every function that is called after this will be stored in the appropriate data file for the thread that is executing the call.

  • stopSaturn

    void stopSaturn(void);

    Ends Saturn profiling. Data collection ceases for this thread until startSaturn is called again. There can be many startSaturn/stopSaturn function call pairs throughout an instrumented application, if you want to see many small segments of execution scattered in different areas.

A Programmatic Example

Below is a basic example using these functions. It shows how you can use a single pair of startSaturn and stopSaturn calls to exclude initialization and shutdown code from your profile. This is a common practice with programs that spend minimal amounts of time in these routines, in order to avoid polluting the profile with the large number of relatively unimportant function calls often found there. Please note that there can be many startSaturn/stopSaturn function call pairs throughout an instrumented application, if you want to focus even further on small segments of execution scattered in different areas.

#include <Saturn.h>
int main()
{
 // Initialize Saturn:
 // The output file will put in the current working directory.
  initSaturn ("");
 
 // Do work that you don't want to measure, like initialization
  . . . init code here . . .
 
  // Start the back-end.
  startSaturn ();
 
  // This portion of the program is measured
  . . . program core here . . .
 
  // Stop the back-end.
  stopSaturn ();
 
  // This isn't measured, again
  . . . shutdown core here . . .
}