Next | Prev | Up | Top | Contents | Index

Using libpdb

libpdb provides five routines:

All libpdb routines return a value of type pdbStatusT, which is a bitmask of error conditions. If the value is zero (PDB_NO_ERROR), the call completed successfully. If the value is nonzero, it is a combination of one or more of the conditions listed in Table C-1:

Errors Returned by libpdb Routines
ErrorMeaning
PDB_OUT_OF_MEMORYAttempt to allocate memory failed.
PDB_SYNTAX_ERRORDatabase contains one or more records that could not be parsed.
PDB_NOT_FOUNDDatabase does not contain the record requested by the application.
PDB_CANT_WRITEDatabase file could not be updated.
PDB_NOT_OPENpdbOpen() was not invoked before calling one of the other libpdb routines.
PDB_ALREADY_OPENpdbOpen() was called while the database is still open (e.g., before pdbClose() is invoked).

Every program must call pdbOpen() before using the database, and pdbClose() when the database is no longer needed. pdbOpen() opens the database file (stored in $HOME/.pdb2 on UNIX systems) and reads all the performance measurements into main memory. pdbClose() releases all memory used by the library, and writes the database back to its file if any changes have been made by invoking pdbWriteRate().

pdbStatusT pdbOpen(void); 
pdbStatusT pdbClose(void);
pdbOpen() returns

pdbClose() returns

Normally applications should look for the performance data they need before going to the trouble of taking measurements. pdbReadRate(), which is used for this, has the following prototype:

pdbStatusT pdbReadRate (const char* machineName,const char* appName,
          const char* benchmarkName,const char* versionString, double* rate )

machineName

A zero-terminated string giving the name of the machine for which the measurement is sought. If NULL, the default machine name is used. (In X11 environments, the display name is an appropriate choice, and the default machine name is the content of the DISPLAY environment variable.)

appName

Name of the application. This is used as an additional database key to reduce accidental collisions between benchmark names.

benchmarkName

Name of the benchmark.

versionString

The fourth argument is a string identifying the desired version of the benchmark. For OpenGL performance measurements, the string returned by glGetString(GL_VERSION) is a good value for this argument. Other applications might use the version number of the benchmark, rather than the version number of the system under test.

rate

A pointer to a double-precision floating-point variable that receives the performance measurement (the "rate") from the database. The rate indicates the number of benchmark operations per second that were measured on a previous run. If pdbReadRate() returns zero, then it completed successfully and the rate is returned in the last argument. If the requested benchmark is not present in the database, it returns PDB_NOT_FOUND. Finally, if pdbReadRate() is called when the database has not been opened by pdbOpen(), it returns PDB_NOT_OPEN.

Example for pdbRead

main() {
        double rate;
        pdbOpen();
        if (pdbReadRate(NULL, "myApp", "triangles",
           glGetString(GL_VERSION), &rate)
              == PDB_NO_ERROR)
        printf("%g triangle calls per second\n", rate);
        pdbClose();
        }
When the application is run for the first time, or when the performance database file has been removed (perhaps to allow a fresh start after a hardware upgrade), pdbReadRate() is not able to find the desired benchmark. If this happens, the application should use pdbMeasureRate(), which has the following prototype, to make a measurement:

pdbStatusT pdbMeasureRate (pdbCallbackT initialize, pdbCallbackT operation, 
                          pdbCallbackT finalize, int calibrate, double* rate)

initialize

A pointer to the initialization function. The initialization function is run before each set of operations. For OpenGL performance measurement, it's appropriate to use glFinish() for initialization, to make sure that the graphics pipe is quiet. However, for other performance measurements, the initialization function can create test data, preload caches, and so on. May be NULL, in which case no initialization is performed.

operation

A pointer to the operation function. This function performs the operations that are to be measured. Usually you'll want to make sure that any global state needed by the operation is set up before calling the operation function, so that you don't include the cost of the setup operations in the measurement.

finalize

A pointer to a finalization function. This is run once, after all the calls to the operation function are complete. In the example above, glFinish() ensures that the graphics pipeline is idle. It may be NULL, in which case no finalization is performed. The finalization function must be calibrated so that the overhead of calling it may be subtracted from the time used by the operation function. If the fourth argument is nonzero, then pdbMeasureRate() calibrates the finalization function. If the fourth argument is zero, then pdbMeasureRate() uses the results of the previous calibration. Recalibrating each measurement is the safest approach, but it roughly doubles the amount of time needed for a measurement. For OpenGL, it should be acceptable to calibrate once and recalibrate only when using a different X11 display.

rate

A pointer to a double-precision floating-point variable that receives the execution rate. This rate is the number of times the operation function was called per second. pdbMeasureRate() attempts to compute a number of repetitions that results in a run time of about one second. (Calibration requires an additional second.) It's reasonably careful about timekeeping on systems with low-resolution clocks.
pdbMeasureRate() always returns PDB_NO_ERROR.


Example for pdbMeasureRate()

void SetupOpenGLState(void) {
        /* set all OpenGL state to desired values */
        }

void DrawTriangles(void) {
        glBegin(GL_TRIANGLE_STRIP);
                /* specify some vertices... */
        glEnd();
        }
main() {
                double rate;
                pdbOpen();
                if (pdbReadRate(NULL, "myApp", "triangles",
                   glGetString(GL_VERSION), &rate)
                      != PDB_NO_ERROR) {
                SetupOpenGLState();
                pdbMeasureRate(glFinish, DrawTriangles,
                    glFinish, 1, &rate);
                }
        printf("%g triangle calls per second\n", rate);
        pdbClose();
        }
Once a rate has been measured, it should be stored in the database by calling pdbWriteRate(), which has the following prototype:

pdbStatusT pdbWriteRate (const char* machineName, const char* applicationName, const char* benchmarkName,const char* versionString, double rate)
The first four arguments of pdbWriteRate() match the first four arguments of pdbReadRate(). The last argument is the performance measurement to be saved in the database.

pdbWriteRate() returns

When pdbWriteRate() is called, the in-memory copy of the performance database is marked "dirty." pdbClose() takes note of this and writes the database back to disk.


Example for pdbWriteRate()

main() {
        double rate;
        pdbOpen();
        if (pdbReadRate(NULL, "myApp", "triangles",
           glGetString(GL_VERSION), &rate)
              != PDB_NO_ERROR) {
                SetupOpenGL();
                pdbMeasureRate(glFinish, DrawTriangles,
                    glFinish, 1, &rate);
                pdbWriteRate(NULL, "myApp", "triangles",
                    glGetString(GL_VERSION), rate);
                }
        printf("%g triangle calls per second\n", rate);
        pdbClose();
        }

Example for pdbRead
Example for pdbMeasureRate()
Example for pdbWriteRate()

Next | Prev | Up | Top | Contents | Index