![]() |
1.4 (revision 3771)
|
This is a short example of how to use the OTF2 writing interface. This example is available as source code in the file otf2_writer_example.c
.
First include the OTF2 header.
#include <otf2/otf2.h>
For this example an additional include statement is necessary.
#include <stdlib.h>
Furthermore this example uses a function delivering dummy timestamps. Real world applications will use a timer like clock_gettime.
static OTF2_TimeStamp get_time( void ) { static uint64_t sequence; return sequence++; }
Define a pre and post flush callback. If no memory is left in OTF2's internal memory buffer or the writer handle is closed a memory buffer flushing routine is triggered. The pre flush callback is triggered right before a buffer flush. It needs to return either OTF2_FLUSH to flush the recorded data to a file or OTF2_NO_FLUSH to supress flushing data to a file. The post flush callback is triggered right after a memory buffer flush. It has to return a current timestamp which is recorded to mark the time spend in a buffer flush. The callbacks are passed via a struct to OTF2.
static OTF2_FlushType pre_flush( void* userData, OTF2_FileType fileType, OTF2_LocationRef location, void* callerData, bool final ) { return OTF2_FLUSH; } static OTF2_TimeStamp post_flush( void* userData, OTF2_FileType fileType, OTF2_LocationRef location ) { return get_time(); } static OTF2_FlushCallbacks flush_callbacks = { .otf2_pre_flush = pre_flush, .otf2_post_flush = post_flush };
Now everything is prepared to begin with the main program.
int main( int argc, char** argv ) {
Create new archive handle.
OTF2_Archive* archive = OTF2_Archive_Open( "ArchivePath", "ArchiveName", OTF2_FILEMODE_WRITE, 1024 * 1024 /* event chunk size */, 4 * 1024 * 1024 /* def chunk size */, OTF2_SUBSTRATE_POSIX, OTF2_COMPRESSION_NONE );
Set the previously defined flush callbacks.
OTF2_Archive_SetFlushCallbacks( archive, &flush_callbacks, NULL );
We will operate in an serial context.
OTF2_Archive_SetSerialCollectiveCallbacks( archive );
Now we can create the event files. Though physical files aren't created yet.
OTF2_Archive_OpenEvtFiles( archive );
Get a local event writer for location 0.
OTF2_EvtWriter* evt_writer = OTF2_Archive_GetEvtWriter( archive, 0 );
Write an enter and a leave record for region 0 to the local event writer.
OTF2_EvtWriter_Enter( evt_writer, NULL, get_time(), 0 /* region */ ); OTF2_EvtWriter_Leave( evt_writer, NULL, get_time(), 0 /* region */ );
Now close the event writer, before closing the event files collectivly.
OTF2_Archive_CloseEvtWriter( archive, evt_writer );
After we wrote all of the events we close the event files again.
OTF2_Archive_CloseEvtFiles( archive );
Now write the global definitions by getting an writer object for it.
OTF2_GlobalDefWriter* global_def_writer = OTF2_Archive_GetGlobalDefWriter( archive );
We need to define the clock used for this trace and the overall timestamp range.
OTF2_GlobalDefWriter_WriteClockProperties( global_def_writer, 1 /* 1 tick per second */, 0 /* epoch */, 2 /* length */ );
Now we can start writing the referenced definitions, starting with the strings.
OTF2_GlobalDefWriter_WriteString( global_def_writer, 0, "" ); OTF2_GlobalDefWriter_WriteString( global_def_writer, 1, "Master Process" ); OTF2_GlobalDefWriter_WriteString( global_def_writer, 2, "Main Thread" ); OTF2_GlobalDefWriter_WriteString( global_def_writer, 3, "MyFunction" ); OTF2_GlobalDefWriter_WriteString( global_def_writer, 4, "Alternative function name (e.g. mangled one)" ); OTF2_GlobalDefWriter_WriteString( global_def_writer, 5, "Computes something" ); OTF2_GlobalDefWriter_WriteString( global_def_writer, 6, "MyHost" ); OTF2_GlobalDefWriter_WriteString( global_def_writer, 7, "node" );
Write definition for the code region which was just entered and left to the global definition writer.
OTF2_GlobalDefWriter_WriteRegion( global_def_writer, 0 /* id */, 3 /* region name */, 4 /* alternative name */, 5 /* description */, OTF2_REGION_ROLE_FUNCTION, OTF2_PARADIGM_USER, OTF2_REGION_FLAG_NONE, 0 /* source file */, 0 /* begin lno */, 0 /* end lno */ );
Write the system tree including a definition for the location group to the global definition writer.
OTF2_GlobalDefWriter_WriteSystemTreeNode( global_def_writer, 0 /* id */, 6 /* name */, 7 /* class */, OTF2_UNDEFINED_SYSTEM_TREE_NODE /* parent */ ); OTF2_GlobalDefWriter_WriteLocationGroup( global_def_writer, 0 /* id */, 1 /* name */, OTF2_LOCATION_GROUP_TYPE_PROCESS, 0 /* system tree */ );
Write a definition for the location to the global definition writer.
OTF2_GlobalDefWriter_WriteLocation( global_def_writer, 0 /* id */, 2 /* name */, OTF2_LOCATION_TYPE_CPU_THREAD, 2 /* # events */, 0 /* location group */ );
At the end, close the archive and exit.
OTF2_Archive_Close( archive ); return EXIT_SUCCESS; }
To compile your program use a command like the following. Note that we need to activate the C99 standard explicitly for GCC.
gcc -std=c99 `otf2-config --cflags` \ -c otf2_writer_example.c \ -o otf2_writer_example.o
Now you can link your program with:
gcc otf2_writer_example.o \ `otf2-config --ldflags` \ `otf2-config --libs` \ -o otf2_writer_example