[ Bottom of Page | Previous Page | Next Page | Contents | Index | Library Home | Legal | Search ]

Performance Tools Guide and Reference

Perfstat API Programming

The perfstat application programming interface (API) is a collection of C programming language subroutines that execute in user space and uses the perfstat kernel extension to extract various AIX performance metrics. System component information is also retrieved from the Object Data Manager (ODM) and returned with the performance metrics.

The perfstat API is both a 32-bit and a 64-bit API, is thread-safe, and does not require root authority.

The API supports extensions so binary compatibility is maintained across all releases. This is accomplished by using one of the parameters in all the API calls to specify the size of the data structure to be returned. This allows the library to easily determine which version is in use, as long as the structures are only growing, which is guaranteed. This releases the user from version dependencies. For the list of extensions made in earlier versions of AIX, see the Change History section.

The perfstat API subroutines reside in the libperfstat.a library and are part of the bos.perf.libperfstat fileset, which is installable from the AIX base installation media and requires that the bos.perf.perfstat fileset is installed. The later contains the kernel extension and is automatically installed with AIX.

The /usr/include/libperfstat.h file contains the interface declarations and type definitions of the data structures to use when calling the interfaces. This include file is also part of the bos.perf.libperfstat fileset. Sample source code is provided with bos.perf.libperfstat and resides in the /usr/samples/libperfstat directory. Detailed information for the individual interfaces and the data structures used can be found in the libperfstat.h file in the AIX 5L Version 5.2 Files Reference.

API Characteristics

Two types of APIs are available. Global types return global metrics related to a set of components, while the individual types return metrics related to individual components. Both types of interfaces have similar signatures, but slightly different behavior.

All the interfaces return raw data; that is, values of running counters. Multiple calls must be made at regular intervals to calculate rates.

Several interfaces return data retrieved from the ODM (object data manager) database. This information is automatically cached into a dictionary that is assumed to be "frozen" after it is loaded. The perfstat_reset subroutine must be called to clear the dictionary whenever the machine configuration has changed.

Most types returned are unsigned long long; that is, unsigned 64-bit data. This provides complete kernel independence. Some kernel internal metrics are in fact 32-bit wide in the 32-bit kernel, and 64-bit wide in the 64-bit kernel. The corresponding libperfstat APIs data type is always unsigned 64-bit.

All of the examples presented in this chapter can be compiled in AIX 5.2 using cc with -lperfstat.

Global Interfaces

Global interfaces report metrics related to a set of components on a system (such as processors, disks, memory).

All of the following AIX 5.2 interfaces use the naming convention perfstat_subsystem_total, and use a common signature:

perfstat_cpu_total Retrieves global CPU usage metrics
perfstat_memory_total Retrieves global memory usage metrics
perfstat_disk_total Retrieves global disk usage metrics
perfstat_netinterface_total Retrieves global network interfaces metrics

The common signature used by all of the global interfaces is as follows:

int perfstat_subsystem_total(perfstat_id_t *name,
                             perfstat_subsystem_total_t *userbuff,
                             int sizeof_struct,
                             int desired_number);

The usage of the parameters for all of the interfaces is as follows:

perfstat_id_t *name Reserved for future use, should be NULL
perfstat_subsystem_total_t *userbuff A pointer to a memory area with enough space for the returned structure
int sizeof_struct Should be set to sizeof(perfstat_subsystem_t)
int desired_number Reserved for future use, must be set to 0 or 1

The return value will be -1 in case of errors. Otherwise, the number of structures copied is returned. This is always 1.

An exception to this scheme is: when name=NULL, userbuff=NULL and desired_number=0, the total number of structures available is returned. This is always 1.

The following sections provide examples of the type of data returned and code using each of the interfaces.

perfstat_cpu_total Interface

The perfstat_cpu_total function returns a perfstat_cpu_total_t structure, which is defined in the libperfstat.h file. Selected fields from the perfstat_cpu_total_t structure include:

processorHz Processor speed in Hertz (from ODM)
description Processor type (from ODM)
ncpus Current number of active CPUs
ncpus_cfg Number of configured CPUs; that is, the maximum number of processors that this copy of AIX can handle simultaneously
ncpus_high Maximum number of active CPUs; that is, the maximum number of active processors since the last reboot
user Total number of clock ticks spent in user mode
sys Total number of clock ticks spent in system (kernel) mode
idle Total number of clock ticks spent idle with no I/O pending
wait Total number of clock ticks spent idle with I/O pending

Several other processor-related counters (such as number of system calls, number of reads, write, forks, execs, and load average) are also returned. For a complete list, see the perfstat_cpu_total_t section of the libperfstat.h header file in AIX 5L Version 5.2 Files Reference.

The following code shows an example of how perfstat_cpu_total is used:

#include <stdio.h>
#include <sys/time.h>
#include <libperfstat.h>

unsigned long long last_tot, last_user, last_sys, last_idle, last_wait;

int
main(int argc, char *argv[]) {
   perfstat_cpu_total_t cpu_total_buffer;
   unsigned long long cur_tot;
   unsigned long long delt_tot, delt_user, delt_sys, delt_idle, delt_wait;

   /* get initial set of data */
   perfstat_cpu_total(NULL, &cpu_total_buffer, sizeof(perfstat_cpu_total_t), 1);

   /* print general processor information */
   printf("Processors: (%d:%d) %s running at %llu MHz\n",
          cpu_total_buffer.ncpus, cpu_total_buffer.ncpus_cfg,
          cpu_total_buffer.description, cpu_total_buffer.processorHZ/1000000);

   /* save values for delta calculations */
   last_tot = cpu_total_buffer.user + cpu_total_buffer.sys  +
              cpu_total_buffer.idle + cpu_total_buffer.wait;

   last_user  = cpu_total_buffer.user;
   last_sys   = cpu_total_buffer.sys;
   last_idle  = cpu_total_buffer.idle;
   last_wait  = cpu_total_buffer.wait;

   printf("\n User    Sys   Idle   Wait  Total  Rate\n");

   while(1 == 1) {
      sleep(1);

      /* get new values after one second */
      perfstat_cpu_total(NULL, &cpu_total_buffer, sizeof(perfstat_cpu_total_t), 1);
                

      /* calculate current total number of ticks */
      cur_tot = cpu_total_buffer.user + cpu_total_buffer.sys  +
                cpu_total_buffer.idle + cpu_total_buffer.wait;

      delt_user = cpu_total_buffer.user - last_user;
      delt_sys  = cpu_total_buffer.sys  - last_sys;
      delt_idle = cpu_total_buffer.idle - last_idle;
      delt_wait = cpu_total_buffer.wait - last_wait;
      delt_tot  = cur_tot - last_tot;

      /* print percentages, total delta ticks and tick rate per cpu per sec */
      printf("%#5.1f  %#5.1f  %#5.1f  %#5.1f  %-5llu  %llu\n",
             100.0 * (double) delt_user / (double) delt_tot,
             100.0 * (double) delt_sys  / (double) delt_tot,
             100.0 * (double) delt_idle / (double) delt_tot,
             100.0 * (double) delt_wait / (double) delt_tot,
             delt_tot, delt_tot/cpu_total_buffer.ncpus);

      /* save current value for next time */
      last_tot  = cur_tot;
      last_user = cpu_total_buffer.user;
      last_sys  = cpu_total_buffer.sys;
      last_idle = cpu_total_buffer.idle;
      last_wait = cpu_total_buffer.wait;
   }
}

The preceding program produces (on a single PowerPc 604e microprocessor-based machine) output similar to the following:

Processors: (1:1) PowerPC_604e running at 375 MHz

 User    Sys   Idle   Wait  Total  Rate
 19.0   31.0    1.0   49.0  100    100
 20.8   34.7    0.0   44.6  101    101
 35.0   30.0    0.0   35.0  100    100
 12.0   20.0    0.0   68.0  100    100
 19.0   33.0    0.0   48.0  100    100
 29.0   43.0   11.0   17.0  100    100
 23.0   30.0   25.0   22.0  100    100
 24.0   25.0   15.0   36.0  100    100
 26.0   27.0   25.0   22.0  100    100
 20.0   32.0   37.0   11.0  100    100
 16.0   22.0   49.0   13.0  100    100
 16.0   33.0   18.0   33.0  100    100

perfstat_memory_total Interface

The perfstat_memory_total function returns a perfstat_memory_total_t structure, which is defined in the libperfstat.h file. Selected fields from the perfstat_memory_total_t structure include:

virt_total Amount of virtual memory (in units of 4 KB pages)
real_total Amount of real memory (in units of 4 KB pages)
real_free Amount of free real memory (in units of 4 KB pages)
real_pinned Amount of pinned memory (in units of 4 KB pages)
pgins Number of pages paged in
pgouts Number of pages paged out
pgsp_total Total amount of paging space (in units of 4 KB pages)
pgsp_free Amount of free paging space (in units of 4 KB pages)
pgsp_rsvd Amount of reserved paging space (in units of 4 KB pages)

Several other memory related metrics (such as number of paging space paged in and out, and amount of system memory) are also returned. For a complete list, see the perfstat_memory_total_t section in libperfstat.h.

The following code shows an example of how perfstat_memory_total is used:

#include <stdio.h>
#include <libperfstat.h>

int main(int argc, char* argv[]) {
    perfstat_memory_total_t minfo;

    perfstat_memory_total(NULL, &minfo, sizeof(perfstat_memory_total_t), 1);

    printf("Memory statistics\n");
    printf("-----------------\n");
    printf("real memory size                 : %llu MB\n",
           minfo.real_total*4096/1024/1024);
    printf("reserved paging space            : %llu MB\n",minfo.pgsp_rsvd);
    printf("virtual memory size              : %llu MB\n",
           minfo.virt_total*4096/1024/1024);
    printf("number of free pages             : %llu\n",minfo.real_free);
    printf("number of pinned pages           : %llu\n",minfo.real_pinned);
    printf("number of pages in file cache    : %llu\n",minfo.numperm);
    printf("total paging space pages         : %llu\n",minfo.pgsp_total);
    printf("free paging space pages          : %llu\n", minfo.pgsp_free);
    printf("used paging space                : %3.2f%%\n",
        (float)(minfo.pgsp_total-minfo.pgsp_free)*100.0/
        (float)minfo.pgsp_total);
    printf("number of paging space page ins  : %llu\n",minfo.pgspins);
    printf("number of paging space page outs : %llu\n",minfo.pgspouts);
    printf("number of page ins               : %llu\n",minfo.pgins);
    printf("number of page outs              : %llu\n",minfo.pgouts);
}

The preceding program produces output similar to the following:

Memory statistics
-----------------
real memory size                 : 256 MB
reserved paging space            : 512 MB
virtual memory size              : 768 MB
number of free pages             : 32304
number of pinned pages           : 6546
number of pages in file cache    : 12881
total paging space pages         : 131072
free paging space pages          : 129932
used paging space                : 0.87%
number of paging space page ins  : 0
number of paging space page outs : 0
number of page ins               : 20574
number of page outs              : 92508

perfstat_disk_total Interface

The perfstat_disk_total function returns a perfstat_disk_total_t structure, which is defined in the libperfstat.h file. Selected fields from the perfstat_disk_total_t structure include:

number Number of disks
size Total disk size (in MB)
free Total free disk space (in MB)
xfers Total transfers to/from disk (in KB)

Several other disk-related metrics, such as number of blocks read from and written to disk, are also returned. For a complete list, see the perfstat_disk_total_t section in libperfstat.h.

The following code shows an example of how perfstat_disk_total is used:

#include <stdio.h>
#include <libperfstat.h>

int main(int argc, char* argv[]) {
    perfstat_disk_total_t dinfo;

    perfstat_disk_total(NULL, &dinfo, sizeof(perfstat_disk_total_t), 1);

    printf("Total disk statistics\n");
    printf("---------------------\n");
    printf("number of  disks         : %d\n",   dinfo.number);
    printf("total disk space         : %llu\n", dinfo.size);
    printf("total free space         : %llu\n", dinfo.free);
    printf("number of transfers      : %llu\n", dinfo.xfers);
    printf("number of blocks written : %llu\n", dinfo.wblks);
    printf("number of blocks read    : %llu\n", dinfo.rblks);
}

This program produces output similar to the following:

Total disk statistics
---------------------
number of  disks         : 3
total disk space         : 4296
total free space         : 2912
number of transfers      : 77759
number of blocks written : 738016
number of blocks read    : 363120

perfstat_netinterface_total Interface

The perfstat_netinterface_total function returns a perfstat_netinterface_total_t structure, which is defined in the libperfstat.h file. Selected fields from the perfstat_netinterface_total_t structure include:

number Number of network interfaces
ipackets Total number of input packets received on all network interfaces
opackets Total number of output packets sent on all network interfaces
ierror Total number of input errors on all network interfaces
oerror Total number of output errors on all network interfaces

Several other network interface related metrics (such as number of bytes sent and received). For a complete list, see the perfstat_netinterface_total_t section in libperfstat.h .

The following code shows an example of how perfstat_netinterface_total is used:

#include <stdio.h>
#include <libperfstat.h>

int main(int argc, char* argv[]) {
    perfstat_netinterface_total_t ninfo;

    perfstat_netinterface_total(NULL, &ninfo, sizeof(perfstat_netinterface_total_t), 1);

    printf("Network interfaces statistics\n");
    printf("-----------------------------\n");
    printf("number of interfaces : %d\n",   ninfo.number);
    printf("\ninput statistics:\n");
    printf("number of packets    : %llu\n", ninfo.ipackets);
    printf("number of errors     : %llu\n", ninfo.ierrors);
    printf("number of bytes      : %llu\n", ninfo.ibytes);
    printf("\noutput statistics:\n");
    printf("number of packets    : %llu\n", ninfo.opackets);
    printf("number of bytes      : %llu\n", ninfo.obytes);
    printf("number of errors     : %llu\n", ninfo.oerrors);
}

The program above produces output similar to this:

Network interfaces statistics
-----------------------------
number of interfaces : 2

input statistics:
number of packets    : 306688
number of errors     : 0
number of bytes      : 24852688

output statistics:
number of packets    : 63005
number of bytes      : 11518591
number of errors     : 0

Component-Specific Interfaces

Component-specific interfaces report metrics related to individual components on a system (such as a processor, disk, network interface, or paging space).

All of the following interfaces use the naming convention perfstat_subsystem, and use a common signature:

perfstat_cpu Retrieves individual CPU usage metrics
perfstat_disk Retrieves individual disk usage metrics
perfstat_diskadapter Retrieves individual disk adapter metrics
perfstat_netinterface Retrieves individual network interfaces metrics
perfstat_protocol Retrieves individual network protocol related metrics
perfstat_netbuffer Retrieves individual network buffer allocation metrics
perfstat_pagingspace Retrieves individual paging space metrics

The common signature used by all the component interfaces is as follows:

int perfstat_subsystem(perfstat_id *name,
                       perfstat_subsystem_t * userbuff,
                       int sizeof_struct,
                       int desired_number);

The usage of the parameters for all of the interfaces is as follows:

perfstat_id_t *name The name of the first component (for example hdisk2 for perfstat_disk()) for which statistics are desired. A structure containing a char * field is used instead of directly passing a char * argument to the function to avoid allocation errors and to prevent the user from giving a constant string as parameter. To start from the first component of a subsystem, set the char* field of the name parameter to "" (empty string). You can also use the macros such as FIRST_SUBSYSTEM (for example,FIRST_CPU) defined in the libperfstat.h file.
perfstat_subsystem_total_t *userbuff A pointer to a memory area with enough space for the returned structure(s).
int sizeof_struct Should be set to sizeof(perfstat_subsystem_t).
int desired_number The number of structures of type perfstat_subsystem_t to return in userbuff.

The return value will be -1 in case of error. Otherwise, the number of structures copied is returned. The field name is either set to NULL or to the name of the next structure available.

An exception to this scheme is when name=NULL, userbuff=NULL and desired_number=0, the total number of structures available is returned.

To retrieve all structures of a given type, either ask first for their number, allocate enough memory to hold them all at once, then call the appropriate API to retrieve them all in one call. Otherwise, allocate a fixed set of structures and repeatedly call the API to get the next such number of structures, each time passing the name returned by the previous call. Start the process with the name set to "" or FIRST_SUBSYSTEM, and repeat the process until the name returned is equal to "".

Minimizing the number of API calls, and therefore the number of system calls, will always lead to more efficient code, so the two-call approach should be preferred. Some of the examples shown in the following sections illustrate the API usage using the two-call approach. Because the two-call approach can lead to a lot of memory being allocated, the multiple-call approach must sometime be used and is illustrated in the following examples.

The following sections provide examples of the type of data returned and code using each of the interfaces.

perfstat_cpu interface

The perfstat_cpu function returns a set of structures of type perfstat_cpu_t, which is defined in the libperfstat.h file. Selected fields from the perfstat_cpu_t structure include:

name Logical CPU name (cpu0, cpu1, ...)
user Number of clock ticks spent in user mode
sys Number of clock ticks spent in system (kernel) mode
idle Number of clock ticks spent idle with no I/O pending
wait Number of clock ticks spent idle with I/O pending
syscall Number of system call executed

Several other CPU related metrics (such as number of forks, read, write, and execs) are also returned. For a complete list, see the perfstat_cpu_t section in the libperfstat.h file.

The following code shows an example of how perfstat_cpu is used:

#include <stdio.h>
#include <stdlib.h>
#include <libperfstat.h>

int main(int argc, char *argv[]) {
   int i, retcode, cputotal;
   perfstat_id_t firstcpu;
   perfstat_cpu_t *statp;
   
   /* check how many perfstat_cpu_t structures are available */
   cputotal =  perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0);
   
   printf("number of perfstat_cpu_t available : %d\n", cputotal);
   
   /* allocate enough memory for all the structures */
   statp = calloc(cputotal,sizeof(perfstat_cpu_t));
   
   /* set name to first cpu */
   strcpy(firstcpu.name, FIRST_CPU);
   
   /* ask to get all the structures available in one call */
   retcode = perfstat_cpu(&firstcpu, statp, sizeof(perfstat_cpu_t), cputotal);
   				 
   /* return code is number of structures returned */
   printf("number of perfstat_cpu_t returned  : %d\n", retcode);
   
   for (i = 0; i < retcode; i++) {
      printf("\nStatistics for CPU : %s\n", statp[i].name);
      printf("------------------\n");
      printf("CPU user time (raw ticks)  : %llu\n", statp[i].user);
      printf("CPU sys  time (raw ticks)  : %llu\n", statp[i].sys);
      printf("CPU idle time (raw ticks)  : %llu\n", statp[i].idle);
      printf("CPU wait time (raw ticks)  : %llu\n", statp[i].wait);
      printf("number of syscalls         : %llu\n", statp[i].syscall);
      printf("number of readings         : %llu\n", statp[i].sysread);
      printf("number of writings         : %llu\n", statp[i].syswrite);
      printf("number of forks            : %llu\n", statp[i].sysfork);
      printf("number of execs            : %llu\n", statp[i].sysexec);
      printf("number of char read        : %llu\n", statp[i].readch);
      printf("number of char written     : %llu\n", statp[i].writech);
      }
}

On a single processor machine, the preceding program produces output similar to the following:

number of perfstat_cpu_t available : 1
number of perfstat_cpu_t returned  : 1

Statistics for CPU : cpu0
------------------
CPU user time (raw ticks)  : 1336297
CPU sys  time (raw ticks)  : 111958
CPU idle time (raw ticks)  : 57069585
CPU wait time (raw ticks)  : 19545
number of syscalls         : 4734311
number of readings         : 562121
number of writings         : 323367
number of forks            : 6839
number of execs            : 7257
number of char read        : 753568874
number of char written     : 132494990

In an environment where dynamic logical partitioning is used, the number of perfstat_cpu_t structures available will always be equal to the ncpus_high field in the perfstat_cpu_total_t. This number represents the highest index of any active processor since the last reboot. Kernel data structures holding performance metrics for processors are not deallocated when processors are turned offline or moved to a different partition. They simply stop being updated. The ncpus field of the perfstat_cpu_total_t structure always represents the number of active processors, but the perfstat_cpu interface will always return ncpus_high structures.

Applications can detect offline or moved processors by checking clock-tick increments. If the sum of the user, sys, idle and wait fields is identical for a given processor between two perfstat_cpu calls, that processor has been offline for the complete interval. If the sum multiplied by 10 ms (the value of a clock tick) does not match the time interval, the processor has not been online for the complete interval.

perfstat_disk Interface

The perfstat_disk function returns a set of structures of type perfstat_disk_t, which is defined in the libperfstat.h file. Selected fields from the perfstat_disk_t structure include:

name Disk name (from ODM)
description Disk description (from ODM)
vgname Volume group name (from ODM)
size Disk size (in MB)
free Free space (in MB)
xfers Transfers to/from disk (in KB)

Several other disk related metrics (such as number of blocks read from and written to disk, and adapter names) are also returned. For a complete list, see the perfstat_disk_t section in the libperfstat.h header file.

The following code shows an example of how perfstat_disk is used:

#include <stdio.h>
#include <stdlib.h>
#include <libperfstat.h>

int main(int argc, char* argv[]) {
    int i, ret, tot;
    perfstat_disk_t *statp;
    perfstat_id_t first;

    /* check how many perfstat_disk_t structures are available */
    tot =  perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0);
    
    /* allocate enough memory for all the structures */
    statp = calloc(tot, sizeof(perfstat_disk_t));
    
    /* set name to first interface */
    strcpy(first.name, FIRST_DISK);
    
    /* ask to get all the structures available in one call */
    /* return code is number of structures returned */
    ret = perfstat_disk(&first, statp,
                        sizeof(perfstat_disk_t), tot);



    /* print statistics for each of the disks */
    for (i = 0; i < ret; i++) {
        printf("\nStatistics for disk : %s\n", statp[i].name);
        printf("-------------------\n");
        printf("description              : %s\n", statp[i].description);
        printf("volume group name        : %s\n", statp[i].vgname);
        printf("adapter name             : %s\n", statp[i].adapter);
        printf("size                     : %llu MB\n", statp[i].size);
        printf("free space               : %llu MB\n", statp[i].free);
        printf("number of blocks read    : %llu\n", statp[i].rblks);
        printf("number of blocks written : %llu\n", statp[i].wblks);
        }
}

The preceding program produces output similar to the following:

Statistics for disk : hdisk1
-------------------
description              : 16 Bit SCSI Disk Drive
volume group name        : rootvg
adapter name             : scsi0
size                     : 4296 MB
free space               : 2912 MB
number of blocks read    : 403946
number of blocks written : 768176

Statistics for disk : hdisk0
-------------------
description              : 16 Bit SCSI Disk Drive
volume group name        : None
adapter name             : scsi0
size                     : 0 MB
free space               : 0 MB
number of blocks read    : 0
number of blocks written : 0

Statistics for disk : cd0
-------------------
description              : SCSI Multimedia CD-ROM Drive
volume group name        : not available
adapter name             : scsi0
size                     : 0 MB
free space               : 0 MB
number of blocks read    : 3128
number of blocks written : 0

perfstat_diskadapter Interface

The perfstat_diskadapter function returns a set of structures of type perfstat_diskadapter_t, which is defined in the libperfstat.h file. Selected fields from the perfstat_diskadapter_t structure include:

name Adapter name (from ODM)
description Adapter description (from ODM)
size Total disk size connected to this adapter (in MB)
free Total free space on disks connected to this adapter (in MB)
xfers Total transfers to/from this adapter (in KB)

Several other disk adapter related metrics (such as the number of blocks read from and written to the adapter) are also returned. For a complete list, see the perfstat_diskadapter_t section in libperfstat.h.

The following code shows an example of how perfstat_diskadapter is used:

#include <stdio.h>
#include <stdlib.h>
#include <libperfstat.h>

int main(int argc, char* argv[]) {
   int i, ret, tot;
   perfstat_diskadapter_t *statp;
   perfstat_id_t first;

   /* check how many perfstat_diskadapter_t structures are available */
   tot = perfstat_diskadapter(NULL, NULL, sizeof(perfstat_diskadapter_t), 0);

   /* allocate enough memory for all the structures */
   statp = calloc(tot, sizeof(perfstat_diskadapter_t));
   
   /* set name to first interface */
   strcpy(first.name, FIRST_DISK);
   
   /* ask to get all the structures available in one call */
   /* return code is number of structures returned */
   ret = perfstat_diskadapter(&first, statp, sizeof(perfstat_diskadapter_t), tot);
   				 
   /* print statistics for each of the disk adapters */
   for (i = 0; i < ret; i++) {
       printf("\nStatistics for adapter : %s\n", statp[i].name);
       printf("----------------------\n");
       printf("description               : %s\n", statp[i].description);
       printf("number of disks connected : %d\n", statp[i].number);
       printf("total disk size           : %llu MB\n", statp[i].size);
       printf("total disk free space     : %llu MB\n", statp[i].free);
       printf("number of blocks read     : %llu\n", statp[i].rblks);
       printf("number of blocks written  : %llu\n", statp[i].wblks);
       }
}

The preceding program produces output similar to the following:

Statistics for adapter : scsi0
----------------------
description               : Wide/Fast-20 SCSI I/O Controller
number of disks connected : 3
total disk size           : 4296 MB
total disk free space     : 2912 MB
number of blocks read     : 411284
number of blocks written  : 768256

perfstat_netinterface Interface

The perfstat_netinterface function returns a set of structures of type perfstat_netinterface_t, which is defined in the libperfstat.h file. Selected fields from the perfstat_netinterface_t structure include:

name Interface name (from ODM)
description Interface description (from ODM)
ipackets Total number of input packets received on this network interface
opackets Total number of output packets sent on this network interface
ierror Total number of input errors on this network interface
oerror Total number of output errors on this network interface

Several other network interface related metrics (such as number of bytes sent and received, type, and bitrate) are also returned. For a complete list, see the perfstat_netinterface_t section in the libperfstat.h file.

The following code shows an example of how perfstat_netinterfaceis used:

#include <stdio.h> 
#include <stdlib.h>
#include <libperfstat.h>
#include <net/if_types.h>

char *
decode(uchar type) {

    switch(type) {

    case IFT_LOOP:
        return("loopback");

    case IFT_ISO88025:
        return("token-ring");

    case IFT_ETHER:
        return("ethernet");
    }

    return("other");
}

int main(int argc, char* argv[]) {
   int i, ret, tot;
   perfstat_netinterface_t *statp;
   perfstat_id_t first;

   /* check how many perfstat_netinterface_t structures are available */
   tot = perfstat_netinterface(NULL, NULL, sizeof(perfstat_netinterface_t), 0);
   
   /* allocate enough memory for all the structures */
   statp = calloc(tot, sizeof(perfstat_netinterface_t));
   
   /* set name to first interface */
   strcpy(first.name, FIRST_NETINTERFACE);
   
   /* ask to get all the structures available in one call */
   /* return code is number of structures returned */
   ret = perfstat_netinterface(&first, statp, sizeof(perfstat_netinterface_t), tot);

   /* print statistics for each of the interfaces */
   for (i = 0; i < ret; i++) {
       printf("\nStatistics for interface : %s\n", statp[i].name);
       printf("------------------------\n");
       printf("type : %s\n", decode(statp[i].type));
       printf("\ninput statistics:\n");
       printf("number of packets : %llu\n", statp[i].ipackets);
       printf("number of errors  : %llu\n", statp[i].ierrors);
       printf("number of bytes   : %llu\n", statp[i].ibytes);
       printf("\noutput statistics:\n");
       printf("number of packets : %llu\n", statp[i].opackets);
       printf("number of bytes   : %llu\n", statp[i].obytes);
       printf("number of errors  : %llu\n", statp[i].oerrors);
       }
}

The preceding program produces output similar to the following:

Statistics for interface : tr0
------------------------
type : token-ring

input statistics:
number of packets : 306352
number of errors  : 0
number of bytes   : 24831776

output statistics:
number of packets : 62669
number of bytes   : 11497679
number of errors  : 0

Statistics for interface : lo0
------------------------
type : loopback

input statistics:
number of packets : 336
number of errors  : 0
number of bytes   : 20912

output statistics:
number of packets : 336
number of bytes   : 20912
number of errors  : 0

perfstat_protocol Interface

The perfstat_protocol function returns a set of structures of type perfstat_protocol_t, which consists of a set of unions to accommodate the different sets of fields needed for each protocol, as defined in the libperfstat.h file. Selected fields from the perfstat_protocol_t structure include:

name protocol name: ip, ip6, icmp, icmp6, udp, tcp, rpc, nfs, nfsv2 or nfsv3.
ipackets Number of input packets received using this protocol. This field exists only for protocols ip, ipv6, udp, and tcp.
opackets Number of output packets sent using this protocol. This field exists only for protocols ip, ipv6, udp, and tcp.
received Number of packets received using this protocol. This field exists only for protocols icmp and icmpv6.
calls Number of calls made to this protocol. This field exists only for protocols rpc, nfs, nfsv2, and nfsv3.

Many other network protocol related metrics are also returned. The complete set of metrics printed by nfsstat is returned for instance. For a complete list, see the perfstat_protocol_t section in the libperfstat.h file.

The following code shows an example of how perfstat_protocol is used:

#include <stdio.h>
#include <string.h>
#include <libperfstat.h>

int main(int argc, char* argv[]) {
    int ret, tot, retrieved = 0;
    perfstat_protocol_t pinfo;
    perfstat_id_t protid;

    /* check how many perfstat_protocol_t structures are available */
    tot = perfstat_protocol(NULL, NULL, sizeof(perfstat_protocol_t), 0);
   
    printf("number of protocol usage structures available : %d\n", tot);

    /* set name to first protocol */
    strcpy(protid.name, FIRST_PROTOCOL);

    /* retrieve first protocol usage information */
    ret = perfstat_protocol(&protid, &pinfo, sizeof(perfstat_protocol_t), 1);
    retrieved += ret;

    do {
       printf("\nStatistics for protocol : %s\n", pinfo.name);
       printf("-----------------------\n");

       if (!strcmp(pinfo.name,"ip")) {
           printf("number of input packets  : %llu\n", pinfo.ip.ipackets);
           printf("number of input errors   : %llu\n", pinfo.ip.ierrors);
           printf("number of output packets : %llu\n", pinfo.ip.opackets);
           printf("number of output errors  : %llu\n", pinfo.ip.oerrors);
       } else if (!strcmp(pinfo.name,"ipv6")) {
           printf("number of input packets  : %llu\n", pinfo.ipv6.ipackets);
           printf("number of input errors   : %llu\n", pinfo.ipv6.ierrors);
           printf("number of output packets : %llu\n", pinfo.ipv6.opackets);
           printf("number of output errors  : %llu\n", pinfo.ipv6.oerrors);
       } else if (!strcmp(pinfo.name,"icmp")) {
           printf("number of packets received : %llu\n", pinfo.icmp.received);
           printf("number of packets sent     : %llu\n", pinfo.icmp.sent);
           printf("number of errors           : %llu\n", pinfo.icmp.errors);
       } else if (!strcmp(pinfo.name,"icmpv6")) {
           printf("number of packets received : %llu\n", pinfo.icmpv6.received);
           printf("number of packets sent     : %llu\n", pinfo.icmpv6.sent);
           printf("number of errors           : %llu\n", pinfo.icmpv6.errors);
       } else if (!strcmp(pinfo.name,"udp")) {
           printf("number of input packets  : %llu\n", pinfo.udp.ipackets);
           printf("number of input errors   : %llu\n", pinfo.udp.ierrors);
           printf("number of output packets : %llu\n", pinfo.udp.opackets);
       } else if (!strcmp(pinfo.name,"tcp")) {
           printf("number of input packets  : %llu\n", pinfo.tcp.ipackets);
           printf("number of input errors   : %llu\n", pinfo.tcp.ierrors);
           printf("number of output packets : %llu\n", pinfo.tcp.opackets);
       } else if (!strcmp(pinfo.name,"rpc")) {
           printf("client statistics:\n");
           printf("number of connection-oriented RPC requests  : %llu\n",
                  pinfo.rpc.client.stream.calls);
           printf("number of rejected connection-oriented RPCs : %llu\n",
                  pinfo.rpc.client.stream.badcalls);
           printf("number of connectionless RPC requests       : %llu\n",
                  pinfo.rpc.client.dgram.calls);
           printf("number of rejected connectionless RPCs      : %llu\n",
                  pinfo.rpc.client.dgram.badcalls);
           printf("\nserver statistics:\n");
           printf("number of connection-oriented RPC requests  : %llu\n",
                  pinfo.rpc.server.stream.calls);
           printf("number of rejected connection-oriented RPCs : %llu\n",
                  pinfo.rpc.server.stream.badcalls);
           printf("number of connectionless RPC requests       : %llu\n",
                  pinfo.rpc.server.dgram.calls);
           printf("number of rejected connectionless RPCs      : %llu\n",
                  pinfo.rpc.server.dgram.badcalls);
       } else if (!strcmp(pinfo.name,"nfs")) {
           printf("total number of NFS client requests        : %llu\n",
                  pinfo.nfs.client.calls);
           printf("total number of NFS client failed calls    : %llu\n",
                  pinfo.nfs.client.badcalls);
           printf("total number of NFS server requests        : %llu\n",
                  pinfo.nfs.server.calls);
           printf("total number of NFS server failed calls    : %llu\n",
                  pinfo.nfs.server.badcalls);
           printf("total number of NFS version 2 server calls : %llu\n",
                  pinfo.nfs.server.public_v2);
           printf("total number of NFS version 3 server calls : %llu\n",
                  pinfo.nfs.server.public_v3);
       } else if (!strcmp(pinfo.name,"nfsv2")) {
           printf("number of NFS V2 client requests : %llu\n",
                  pinfo.nfsv2.client.calls);
           printf("number of NFS V2 server requests : %llu\n",
                  pinfo.nfsv2.server.calls);
       } else if (!strcmp(pinfo.name,"nfsv3")) {
           printf("number of NFS V3 client requests : %llu\n",
                  pinfo.nfsv3.client.calls);
           printf("number of NFS V3 server requests : %llu\n",
                  pinfo.nfsv3.server.calls);
       }

       /* make sure we stop after the last protocol */
       if (ret = strcmp(protid.name, "")) {
           printf("\nnext protocol name : %s\n", protid.name);

           /* retrieve information for next protocol */
           ret = perfstat_protocol(&protid, &pinfo, sizeof(perfstat_protocol_t), 1);
           retrieved += ret;
       }
    } while (ret == 1);

   printf("\nnumber of protocol usage structures retrieved : %d\n", retrieved);
}

The preceding program produces output similar to the following:

number of protocol usage structures available : 10

Statistics for protocol : ip
-----------------------
number of input packets  : 142839
number of input errors   : 54665
number of output packets : 63974
number of output errors  : 55878

next protocol name : ipv6

Statistics for protocol : ipv6
-----------------------
number of input packets  : 0
number of input errors   : 0
number of output packets : 0
number of output errors  : 0

next protocol name : icmp

Statistics for protocol : icmp
-----------------------
number of packets received : 35
number of packets sent     : 1217
number of errors           : 0

next protocol name : icmpv6

Statistics for protocol : icmpv6
-----------------------
number of packets received : 0
number of packets sent     : 0
number of errors           : 0

next protocol name : udp

Statistics for protocol : udp
-----------------------
number of input packets  : 4316
number of input errors   : 0
number of output packets : 308

next protocol name : tcp

Statistics for protocol : tcp
-----------------------
number of input packets  : 82604
number of input errors   : 0
number of output packets : 62250

next protocol name : rpc

Statistics for protocol : rpc
-----------------------
client statistics:
number of connection-oriented RPC requests  : 375
number of rejected connection-oriented RPCs : 0
number of connectionless RPC requests       : 20
number of rejected connectionless RPCs      : 0

server statistics:
number of connection-oriented RPC requests  : 32
number of rejected connection-oriented RPCs : 0
number of connectionless RPC requests       : 0
number of rejected connectionless RPCs      : 0

next protocol name : nfs

Statistics for protocol : nfs
-----------------------
total number of NFS client requests        : 375
total number of NFS client failed calls    : 0
total number of NFS server requests        : 32
total number of NFS server failed calls    : 0
total number of NFS version 2 server calls : 0
total number of NFS version 3 server calls : 0

next protocol name : nfsv2

Statistics for protocol : nfsv2
-----------------------
number of NFS V2 client requests : 0
number of NFS V2 server requests : 0

next protocol name : nfsv3

Statistics for protocol : nfsv3
-----------------------
number of NFS V3 client requests : 375
number of NFS V3 server requests : 32

number of protocol usage structures retrieved : 10

perfstat_netbuffer Interface

The perfstat_netbuffer function returns a set of structures of type perfstat_netbuffer_t, which is defined in the libperfstat.hfile. Selected fields from the perfstat_netbuffer_t structure include:

size Size of the allocation (string expressing size in bytes)
inuse Current allocation of this size
failed Failed allocation of this size
free Free list for this size

Several other allocation related metrics (such as high-water mark and freed) are also returned. For a complete list, see the perfstat_netbuffer_t section in the libperfstat.h file.

The following code shows an example of how perfstat_netbuffer is used:

#include <stdio.h>
#include <stdlib.h>
#include <libperfstat.h>

int main(int argc, char* argv[]) {
   int i, ret, tot;
   perfstat_netbuffer_t *statp;
   perfstat_id_t first;

   /* check how many perfstat_netbuffer_t structures are available */
   tot = perfstat_netbuffer(NULL, NULL, sizeof(perfstat_netbuffer_t), 0);
   
   /* allocate enough memory for all the structures */
   statp = calloc(tot, sizeof(perfstat_netbuffer_t));
   
   /* set name to first interface */
   strcpy(first.name, FIRST_NETBUFFER);
   
   /* ask to get all the structures available in one call */
   /* return code is number of structures returned */
   ret = perfstat_netbuffer(&first, statp,
                          sizeof(perfstat_netbuffer_t), tot);
   				 
   /* print info in netstat -m format */
   printf("%-12s %10s %9s %6s %9s %7s %7s %7s\n",
          "By size", "inuse", "calls", "failed",
          "delayed", "free", "hiwat", "freed");
   for (i = 0; i < ret; i++) {
       printf("%-12s %10llu %9llu %6llu %9llu %7llu %7llu %7llu\n",
           statp[i].name,
           statp[i].inuse,
           statp[i].calls,
           statp[i].delayed,
           statp[i].free,
           statp[i].failed,
           statp[i].highwatermark,
           statp[i].freed);
       }
}

The preceding program produces output similar to the following:

By size           inuse     calls failed   delayed    free   hiwat   freed
32                  199      4798      0        57       0     826       0
64                   96      8121      0        32       0     413       0
128                 110     50156      0       146       0     206       2
256                 279  20313587      0       361       0     496       0
512                 156      5298      0        12       0      51       0
1024                 38      1038      0         6       0     129       0
2048                  1      6946      0       129       0     129    1024
4096                 67    276102      0       132       0     155       0
8192                  4       123      0         4       0      12       0
16384                 1         1      0        15       0      31       0
65536                 1         1      0         0       0     512       0

perfstat_pagingspace Interface

The perfstat_pagingspace function returns a set of structures of type perfstat_pagingspace_t, which is defined in the libperfstat.h file. Selected fields from the perfstat_pagingspace_t structure include:

mb_size Size of the paging space in MB
lp_size Size of the paging space in logical partitions
mb_used Portion of the paging space used in MB

Several other paging space related metrics (such as name, type, and active) are also returned. For a complete list, see the perfstat_pagingspace_t section in the libperfstat.h file.

The following code shows an example of how perfstat_pagingspace is used:

#include <stdio.h>
#include <stdlib.h>
#include <libperfstat.h>

int main(int argc, char agrv[]) {
    int i, ret, tot;
    perfstat_id_t first;
    perfstat_pagingspace_t *pinfo;
    
    tot = perfstat_pagingspace(NULL, NULL, sizeof(perfstat_pagingspace_t), 0);

    pinfo = calloc(tot,sizeof(perfstat_pagingspace_t));

    strcpy(first.name, FIRST_PAGINGSPACE);

    ret = perfstat_pagingspace(&first, pinfo, sizeof(perfstat_pagingspace_t), tot);
    for (i = 0; i < ret; i++) {
        printf("\nStatistics for paging space : %s\n", pinfo[i].name);
        printf("---------------------------\n");
        printf("type         : %s\n",
               pinfo[i].type == LV_PAGING ? "logical volume" : "NFS file");
        if (pinfo[i].type == LV_PAGING) {
    	    printf("volume group : %s\n", pinfo[i].lv_paging.vgname);
        }
        else {
    	    printf("hostname : %s\n", pinfo[i].nfs_paging.hostname);
    	    printf("filename : %s\n", pinfo[i].nfs_paging.filename);
        }
        printf("size (in LP) : %llu\n", pinfo[i].lp_size);
        printf("size (in MB) : %llu\n", pinfo[i].mb_size);
        printf("used (in MB) : %llu\n", pinfo[i].mb_used);
    }
}

The preceding program produces output similar to the following:

Statistics for paging space : hd6
---------------------------
type         : logical volume
volume group : rootvg
size (in LP) : 64
size (in MB) : 512
used (in MB) : 4

Change History

The following additions have been made to the perfstat tool:

Interface Additions

The following interfaces were added in AIX 5.2:

Field Additions

The following additions have been made to the specified AIX release.

AIX Release 5.1.0.15

The following fields were added to perfstat_cpu_total_t:

    u_longlong_t bread
    u_longlong_t bwrite
    u_longlong_t lread
    u_longlong_t lwrite
    u_longlong_t phread
    u_longlong_t phwrite

Support for C++ was added in this AIX level.

Note that the AIX 4.3.3 version of libperfstat is synchronized with this level. No binary or source compatibility is provided between the AIX 4.3.3 version and any AIX 5.1 version prior to 5.1.0.15.

AIX Release 5.1.0.25

The following fields were added to perfstat_cpu_t:

    u_longlong_t bread
    u_longlong_t bwrite
    u_longlong_t lread
    u_longlong_t lwrite
    u_longlong_t phread
    u_longlong_t phwrite

AIX Release 5.2.0

The following fields were added to perfstat_cpu_t:

    u_longlong_t iget
    u_longlong_t namei
    u_longlong_t dirblk
    u_longlong_t msg
    u_longlong_t sema

The name field which returns the logical processor name is now of the form cpu0, cpu1, ... instead of proc0, proc1, ... as it was in previous releases.

The following fields were added to perfstat_cpu_total_t:

    u_longlong_t runocc
    u_longlong_t swpocc
    u_longlong_t iget
    u_longlong_t namei
    u_longlong_t dirblk
    u_longlong_t msg
    u_longlong_t sema
    u_longlong_t rcvint
    u_longlong_t xmtint
    u_longlong_t mdmint
    u_longlong_t tty_rawinch
    u_longlong_t tty_caninch
    u_longlong_t tty_rawoutch
    u_longlong_t ksched
    u_longlong_t koverf
    u_longlong_t kexit
    u_longlong_t rbread
    u_longlong_t rcread
    u_longlong_t rbwrt
    u_longlong_t rcwrt
    u_longlong_t traps
    int ncpus_high

The following field was added to perfstat_disk_t:

       char adapter[IDENTIFIER_LENGTH]

The following field was added to perfstat_netinterface_t:

       u_longlong_t bitrate

The following fields were added to perfstat_memory_total_t:

     u_longlong_t real_system
     u_longlong_t real_user
     u_longlong_t real_process 

The following defines were added to libperfstat.h:

    #define FIRST_CPU          ""
    #define FIRST_DISK         ""
    #define FIRST_DISKADAPTER  ""
    #define FIRST_NETINTERFACE ""
    #define FIRST_PAGINGSPACE  ""
    #define FIRST_PROTOCOL     ""
    #define FIRST_ALLOC        ""

Related Information

The libperfstat.h file

[ Top of Page | Previous Page | Next Page | Contents | Index | Library Home | Legal | Search ]