282 Chapter 8
Ways to Improve Performance
Profile-Based Optimization
Sharing the flow.data File Among Multiple Processes
A flow.data file can potentially be accessed by several processes at the
same time. For example, this could happen when you run more than one
instrumented program at the same time in the same directory, or when
profiling one program while linking another with -P.
Such asynchronous access to the file could potentially corrupt the data.
To prevent simultaneous access to the flow.data file in a particular
directory, a lock file called flow.lock is used. Instrumented programs
that need to update the flow.data file and linker processes that need to
read it must first obtain access to the lock file. Only one process can hold
the lock at any time. As long as the flow.data file is being actively read
and written, a process will wait for the lock to become available.
A program that terminates abnormally may leave the flow.data file
inactive but locked. A process that tries to access an inactive but locked
flow.data file gives up after a short period of time. In such cases, you
may need to remove the flow.lock file.
If an instrumented program fails to obtain the database lock, it writes
the profile data to a temporary file and displays a warning message
containing the name of the file. You could then use the +df option along
with the +P option while optimizing, to specify the name of the
temporary file instead of the flow.data file.
If the linker fails to obtain the lock, it displays an error message and
terminates. In such cases, wait until all active processes that are reading
or writing a profile database file in that directory have completed. If no
such processes exist, remove the flow.lock file.
Forking an Instrumented Application
When instrumenting an application that creates a copy of itself with the
fork system call, you must ensure that the child process calls a special
function named _clear_counters(), which clears all internal profile
data. If you don't do this, the child process inherits the parent's profile
data, updating the data as it executes, resulting in inaccurate
(exaggerated) profile data when the child terminates. The following code
segment shows a valid way to call _clear_counters:
if ((pid = fork()) == 0) /* this is the child process */
{
_clear_counters(); /* reset profile data for child */
. . . /* other code for the child */
}