perfstat_cpu_total Interface
The perfstat_cpu_total interface 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:
Item | Descriptor |
---|---|
purr_coalescing | PURR cycles consumes coalescing data if the calling partition is authorized to see pool wide statistics, else set to zero. |
spurr_coalescing | SPURR cycles consumes coalescing data if the calling partition is authorized to see pool wide statistics, else set to zero. |
processorHz | Processor speed in Hertz (from ODM) |
description | Processor type (from ODM) |
CPUs | Current number of active processors |
ncpus_cfg | Number of configured processors; that is, the maximum number of processors that this copy of AIX® can handle simultaneously |
ncpus_high | Maximum number of active processors; that is, the maximum number of active processors since the last reboot |
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 |
Note: Page coalescing is a transparent operation wherein the hypervisor detects duplicate
pages, directs all user reads to a single copy, and reclaims the other duplicate physical memory
pages.
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.The following program emulates lparstat's behavior and also shows an example of how the
perfstat_cpu_total interface is used:
#include <stdio.h>
#include <sys/time.h>
#include <sys/errno.h>
#include <sys/proc.h>
#include <wpars/wparcfg.h>
#include <libperfstat.h>
#include <stdlib.h>
/* default values for interval and count */
#define INTERVAL_DEFAULT 1
#define COUNT_DEFAULT 1
/* values for wpar status */
#define ACTIVE 0
#define NOTACTIVE 1
/* Check value returned by malloc for NULL */
#define CHECK_FOR_MALLOC_NULL(X) { if ((X) == NULL) {\
perror ("malloc");\
exit(2);\
}\
}
/* Non zero WPAR ID indicates WPAR */
#define IS_WPAR(X) ((X))
/* stores wpar id for perfstat library */
perfstat_id_wpar_t wparid;
perfstat_wpar_total_t wparinfo;
perfstat_wpar_total_t *wparlist;
/*Corral id for WPAR */
cid_t cid;
int interval = INTERVAL_DEFAULT, count = COUNT_DEFAULT;
int totalwpar, activewpar; /* to store and number of wpars available and active wpars */
/*
*Name: do_cleanup
* free all allocated data structures
*/
void do_cleanup(void)
{
if (wparlist)
free(wparlist);
}
/*
*Name: display_global_sysinfo_stat
* Function used when called from global.
* Gets all the system metrics using perfstat APIs and displays them
*
*/
void display_global_sysinfo_stat(void)
{
perfstat_cpu_total_t *cpustat,*cpustat_last;
perfstat_id_t first;
/* allocate memory for data structures and check for any error */
cpustat = (perfstat_cpu_total_t *)malloc(sizeof(perfstat_cpu_total_t));
CHECK_FOR_MALLOC_NULL(cpustat);
cpustat_last = (perfstat_cpu_total_t *)malloc(sizeof(perfstat_cpu_total_t));
CHECK_FOR_MALLOC_NULL(cpustat_last);
/* get the system wide statistics */
if (perfstat_cpu_total(NULL , cpustat_last, sizeof(perfstat_cpu_total_t), 1) <= 0){
perror("perfstat_cpu_total ");
exit(1);
}
printf ("%10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s\n", "cswch", "scalls", "sread", "swrite", "fork", "exec",
"rchar", "wchar", "deviceint", "bwrite", "bread", "phread");
printf ("%10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s\n", "=====", "======", "=====", "======", "====", "====",
"=====", "=====", "=========", "======", "=====", "======");
while (count > 0){
sleep(interval);
if (perfstat_cpu_total(NULL ,cpustat, sizeof(perfstat_cpu_total_t), 1) <= 0){
perror("perfstat_cpu_total ");
exit(1);
}
/* print the difference between the old structure and new structure */
printf("%10llu %10llu %10llu %10llu %10llu %10llu %10llu %10llu %10llu %10llu %10llu %10llu\n",(cpustat->pswitch - cpustat_last->pswitch),
(cpustat->syscall - cpustat_last->syscall), (cpustat->sysread - cpustat_last->sysread ),
(cpustat->syswrite - cpustat_last->syswrite),(cpustat->sysfork - cpustat_last->sysfork),
(cpustat->sysexec - cpustat_last->sysexec ), (cpustat->readch - cpustat_last->readch),
(cpustat->writech - cpustat_last->writech ),(cpustat->devintrs - cpustat_last->devintrs),
(cpustat->bwrite - cpustat_last->bwrite), (cpustat->bread - cpustat_last->bread ),
(cpustat->phread - cpustat_last->phread ));
count--;
/*copy the present structure to the old structure */
memcpy(cpustat_last , cpustat , sizeof(perfstat_cpu_total_t));
}
/* free the memory allocated for the data structures */
free(cpustat);
free(cpustat_last);
}
/*
*Name: display_wpar_sysinfo_stat
* Displays both wpar and global metrics
*
*/
void display_wpar_sysinfo_stat(void)
{
perfstat_wpar_total_t wparinfo;
perfstat_cpu_total_wpar_t cinfo_wpar, cinfo_wpar_last;
perfstat_cpu_total_t sysinfo, sysinfo_last;
/* ste the spec and pass the wparname */
wparid.spec = WPARNAME;
strcpy(wparid.u.wparname, NULL);
/* save the number of wpars which are active */
activewpar = perfstat_wpar_total( NULL , &wparinfo ,sizeof(perfstat_wpar_total_t), 1);
/* if the activewpar is less than zero exit with a perror */
if (activewpar < 0){
perror("perfstat_wpar_total :");
exit(1);
}
/* if the wpar is not active exit with a message */
if (activewpar == 0){
printf("wpar not active \n");
exit(1);
}
/* get the wpar wide cpu information */
if (perfstat_cpu_total_wpar(NULL, &cinfo_wpar_last, sizeof(perfstat_cpu_total_wpar_t), 1) <=0){
perror("perfstat_cpu_total_wpar :");
exit(1);
}
if (perfstat_cpu_total(NULL , &sysinfo_last, sizeof(perfstat_cpu_total_t), 1) <=0){
perror("perfstat_cpu_total_wpar :");
exit(1);
}
printf("%10s %10s %10s %10s %10s %10s %10s %10s\n","wparname ", "cswch" , "syscalls", "fork","runque", "swpque", "runocc", "swpocc" );
printf("%10s %10s %10s %10s %10s %10s %10s %10s\n","======== ", "=====" , "========", "====","======", "======", "======", "======" );
while (count > 0){
sleep(interval);
if (perfstat_cpu_total_wpar( NULL,&cinfo_wpar, sizeof(perfstat_cpu_total_wpar_t), 1) <=0){
perror("perfstat_cpu_total_wpar :");
exit(1);
}
if (perfstat_cpu_total(NULL, &sysinfo, sizeof(perfstat_cpu_total_t), 1) <=0){
perror("perfstat_cpu_total :");
exit(1);
}
/* display the difference between the current and old structure for the current wpar and system wide values*/
printf("%10s %10llu %10llu %10llu %10llu %10llu %10llu %10llu\n",wparinfo.name, (cinfo_wpar.pswitch - cinfo_wpar_last.pswitch),
(cinfo_wpar.syscall - cinfo_wpar_last.syscall), (cinfo_wpar.sysfork - cinfo_wpar_last.sysfork),
(cinfo_wpar.runque - cinfo_wpar_last.runque), (cinfo_wpar.swpque - cinfo_wpar_last.swpque),
(cinfo_wpar.runocc - cinfo_wpar_last.runocc), (cinfo_wpar.swpocc - cinfo_wpar_last.swpocc));
printf("%10s %10llu %10llu %10llu %10llu %10llu %10llu %10llu\n\n", "Global", (sysinfo.pswitch - sysinfo_last.pswitch),
(sysinfo.syscall - sysinfo_last.syscall), (sysinfo.sysfork - sysinfo_last.sysfork),
(sysinfo.runque - sysinfo_last.runque), (sysinfo.swpque - sysinfo_last.swpque),
(sysinfo.runocc - sysinfo_last.runocc), (sysinfo.swpocc - sysinfo_last.swpocc));
count--;
/* copy the data to the old structure */
memcpy(&cinfo_wpar_last, &cinfo_wpar, sizeof(perfstat_wpar_total_t));
memcpy(&sysinfo_last , &sysinfo , sizeof(perfstat_cpu_total_t));
}
}
/* Name: display_wpar_total_sysinfo_stat
* displays statistics of individual wpar
*
*/
int display_wpar_total_sysinfo_stat(void)
{
int i, *status;
perfstat_wpar_total_t *wparinfo;
perfstat_cpu_total_wpar_t *cinfo_wpar, *cinfo_wpar_last;
/* allocate memory for the datastructures and check for any error */
status = (int *) calloc(totalwpar ,sizeof(int));
CHECK_FOR_MALLOC_NULL(status);
cinfo_wpar = (perfstat_cpu_total_wpar_t *) malloc(sizeof (perfstat_cpu_total_wpar_t) * totalwpar);
CHECK_FOR_MALLOC_NULL(cinfo_wpar);
cinfo_wpar_last = (perfstat_cpu_total_wpar_t *) malloc(sizeof (perfstat_cpu_total_wpar_t) * totalwpar);
CHECK_FOR_MALLOC_NULL(cinfo_wpar_last);
wparlist = (perfstat_wpar_total_t *) malloc(sizeof(perfstat_wpar_total_t) * totalwpar);
CHECK_FOR_MALLOC_NULL(wparlist);
activewpar = perfstat_wpar_total(&wparid, wparlist, sizeof(perfstat_wpar_total_t), totalwpar);
if (activewpar < 0){
perror("perfstat_wpar_total :");
exit(1);
}
/* If no active wpars exit with a message */
if (activewpar == 0){
printf("no active wpars found \n");
exit(1);
}
for (i = 0; i < activewpar; i++){
/* copy the wparname into wparid and collect the data for all active wpars */
strcpy(wparid.u.wparname, wparlist[i].name);
if (perfstat_cpu_total_wpar(&wparid, &cinfo_wpar_last[i], sizeof(perfstat_cpu_total_wpar_t), 1) <= 0){
status[i] = NOTACTIVE;
continue;
}
}
/*print the headers */
printf("%20s %12s %12s %12s %12s %12s %12s %12s\n","wparname", "cswitch", "fork", "runque", "swpque", "runocc", "swpocc", "syscalls");
printf("%20s %12s %12s %12s %12s %12s %12s %12s\n","========", "=======", "====", "======", "======", "======", "======", "========");
while (count > 0){
sleep(interval);
for (i = 0; i < activewpar; i++){
strcpy(wparid.u.wparname, wparlist[i].name);
if (perfstat_cpu_total_wpar(&wparid, &cinfo_wpar[i], sizeof(perfstat_cpu_total_wpar_t), 1) <= 0){
status[i] = NOTACTIVE;
continue;
}
}
/* print the data for all active wpars */
for (i = 0; i < activewpar; i++){
if(status[i] == ACTIVE)
printf("%20s %12llu %12llu %12llu %12llu %12llu %12llu %12llu\n", wparlist[i].name,
(cinfo_wpar[i].pswitch - cinfo_wpar_last[i].pswitch), (cinfo_wpar[i].sysfork - cinfo_wpar_last[i].sysfork),
(cinfo_wpar[i].runque - cinfo_wpar_last[i].runque), (cinfo_wpar[i].swpque - cinfo_wpar_last[i].swpque),
(cinfo_wpar[i].runocc - cinfo_wpar_last[i].runocc), (cinfo_wpar[i].swpocc - cinfo_wpar_last[i].swpocc),
(cinfo_wpar[i].syscall- cinfo_wpar_last[i].syscall));
}
printf("\n");
count--;
memcpy(cinfo_wpar_last,cinfo_wpar,(totalwpar * sizeof(perfstat_cpu_total_wpar_t)));
}
/* free all the memory structures */
free(cinfo_wpar);
free(cinfo_wpar_last);
free(status);
}
/*
*Name: showusage
* displays the usage message
*
*/
void showusage()
{
if (!cid)
printf("Usage:simplesysinfo [-@ { ALL | WPARNAME }] [interval] [count]\n ");
else
printf("Usage:simplesysinfo [interval] [count]\n");
exit(1);
}
/* NAME: main
* This function determines the interval, iteration count.
* Then it calls the corresponding functions to display
* the corresponding metrics
*/
int main(int argc, char* argv[])
{
int rc ,atflag = 0, c;
char wpar[MAXCORRALNAMELEN+1];
strcpy(wpar, NULL);
cid = corral_getcid();
while((c = getopt(argc, argv, "@:"))!= EOF){
if (c == '@'){
if (IS_WPAR(cid))
showusage();
atflag = 1;
strcpy(wpar, optarg);
}
}
argc -= optind;
argv += optind;
if (argc > 2)
showusage();
if (argc){
if ((interval = atoi(argv[0])) <= 0)
showusage();
argc--;
}
if (argc){
if ((count = atoi(argv[1])) <= 0)
showusage();
}
/* If no -@ flag call display_global_sysinfo_stat function */
if (!atflag ){
if (!cid)
/*display global values */
display_global_sysinfo_stat();
else
/* display wpar values */
display_wpar_sysinfo_stat();
}
else{
/* if the argument to -@ is not ALL set the totalwpars to 1 */
if (strcmp(wpar, "ALL")) {
strcpy(wparid.u.wparname, wpar);
wparid.spec = WPARNAME;
totalwpar = 1;
}
else{
totalwpar = perfstat_wpar_total(NULL, NULL, sizeof(perfstat_wpar_total_t), 0);
if (totalwpar < 0){
perror("perfstat_wpar_total : ");
exit(1);
}
if (totalwpar == 0){
printf("No wpars found");
exit(1);
}
wparid.spec = WPARNAME;
strcpy(wparid.u.wparname, NULL);
}
display_wpar_total_sysinfo_stat();
}
do_cleanup();
return(0);
}
The
program displays an output that is similar to the following example
output:cswch scalls sread swrite fork exec rchar wchar deviceint bwrite bread phread
===== ====== ===== ====== ==== ==== ===== ===== ========= ====== ===== ======
83 525 133 2 0 1 1009462 264 27 0 0 0