HPX - High Performance ParalleX

Exposing Performance Counter Data using a Simple Function

The simplest way to expose arbitrary numeric data is to write a function which will then be called whenever a consumer queries this counter. Currently, this type of Performance Counter can only be used to expose integer values. The expected signature of this function is:

boost::int64_t some_performance_data(bool reset);

The argument bool reset (which is supplied by the runtime system when the function is invoked) specifies whether the counter value should be reset after evaluating the current value (if applicable).

For instance, here is such a function returning how often it was invoked:

// The atomic variable 'counter' ensures the thread safety of the counter.
boost::atomic<boost::int64_t> counter(0);

boost::int64_t some_performance_data(bool reset)
    boost::int64_t result = ++counter;
    if (reset)
        counter = 0;
    return result;

This example function exposes a linearly increasing value as our performance data. The value is incrememnted on each invocation, e.g. each time a consumer requests the counter data of this Performance Counter.

The next step in exposing this counter to the runtime system is to register the function as a new raw counter type using the HPX API function hpx::performance_counters::install_counter_type. A counter type represents certain common characteristics of counters, like their counter type name, and any associated description information. The following snippet shows an example of how to register the function some_performance_data which is shown above for a counter type named "/test/data". This registration has to be executed before any consumer instantiates and queries an instance of this counter type.

#include <hpx/include/performance_counters.hpp>

void register_counter_type()
    // Call the HPX API function to register the counter type.
        "/test/data",                                   // counter type name
        &some_performance_data,                         // function providing counter data
        "returns a linearly increasing counter value"   // description text (optional)
        ""                                              // unit of measure (optional)

Now it is possible to instantiate a new counter instance based on the naming scheme "/test{locality#*/total}/data", where '*' is a zero based integer index indentifying the locality for which the counter instance should be accessed. The function install_counter_type enables to instantiate exactly one counter instance for each locality. Repeated requests to instantiate such a counter will return the same instance, e.g. the instance created for the first request.

If this counter needs to be accessed using the standard HPX command line options, the registration has to be performed during application startup, before hpx_main is executed. The best way to achieve this is to register an HPX startup function using the API function hpx::register_startup_function before calling hpx::init to initialize the runtime system:

int main(int argc, char* argv[])
    // By registering the counter type we make it available to any consumer
    // who creates and queries an instance of the type "/test/data".
    // This registration should be performed during startup. The
    // function 'register_counter_type' should be executed as an HPX thread right
    // before hpx_main is executed.

    // Initialize and run HPX.
    return hpx::init(argc, argv);

Please see the code in simplest_performance_counter.cpp for a full example demonstrating this functionality.