/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* bos720 src/bos/usr/ccs/lib/libperfstat/simplevmstat.c 1.2.1.2 */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* Restricted Materials of IBM */ /* */ /* COPYRIGHT International Business Machines Corp. 2008,2010 */ /* All Rights Reserved */ /* */ /* US Government Users Restricted Rights - Use, duplication or */ /* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* */ /* IBM_PROLOG_END_TAG */ static char sccsid[] = "@(#)53 1.2.1.2 src/bos/usr/ccs/lib/libperfstat/simplevmstat.c, libperfstat, bos720 6/30/10 06:04:16"; /* * This sample program simulates vmstat command with the option "-IP ALL". */ #include #include #include #include #define INTERVAL_DEFAULT 2 #define COUNT_DEFAULT 10 static perfstat_memory_page_t *psize_mem_values, *last_psize_mem_values; static perfstat_memory_total_t *vmtotal_mem_values, *last_vmtotal_mem_values; static int total_psizes,avail_psizes; static perfstat_cpu_total_t lcpu_values; static u_longlong_t last_lcpu_user, last_lcpu_sys, last_lcpu_idle, last_lcpu_wait; /* support for remote node statistics collection in a cluster environment */ static perfstat_id_node_t nodeid; static char nodename[MAXHOSTNAMELEN] = ""; static int collect_remote_node_stats = 0; static int do_initialization(void); static int collect_metrics_pgsz(void); static int collect_metrics_total(void); static void do_cleanup(void); static int display_psize_memory_stats(void); static int display_total_memory_stats(void); static void save_last_values_pgsz(void); static void save_last_values_total(void); /* * NAME: main * This function determines the interval, iteration count. * Then it calls functions to do initialization, displays statistics * and finally does cleanup befor exiting. * * RETURNS: * On successful completion: * - returns 0. * In case of error * - returns -1. */ int main(int argc, char* argv[]) { int interval = INTERVAL_DEFAULT; int count = COUNT_DEFAULT; int i, rc; char *optlist = "i:c:n:"; /* Process the arguments */ while ((i = getopt(argc, argv, optlist)) != EOF) { switch(i) { case 'i': /* Interval */ interval = atoi(optarg); if( interval <= 0 ) interval = INTERVAL_DEFAULT; break; case 'c': /* Number of interations */ count = atoi(optarg); if( count <= 0 ) count = COUNT_DEFAULT; break; case 'n': /* Node name in a cluster environment */ strncpy(nodename, optarg, MAXHOSTNAMELEN); nodename[MAXHOSTNAMELEN-1] = '\0'; collect_remote_node_stats = 1; break; default: /* Invalid arguments. Print the usage and terminate */ fprintf (stderr, "usage: %s [-i ] [-c ] [-n ]\n", argv[0]); return(-1); } } if(collect_remote_node_stats) { /* perfstat_config needs to be called to enable cluster statistics collection */ rc = perfstat_config(PERFSTAT_ENABLE|PERFSTAT_CLUSTER_STATS, NULL); if (rc == -1) { perror("cluster statistics collection is not available"); exit(-1); } } /* Initialize the data structures */ rc = do_initialization(); if(rc == 0) { if(collect_remote_node_stats) { fprintf (stdout,"Node name = %s\n", nodename); } /* Iterate "count" times */ while (count > 0) { sleep(interval); /* print the header */ fprintf (stdout," Multiple page size statistics\n"); fprintf (stdout, "pgsz memory page\n"); fprintf(stdout, "------- ------------------------------- ------------------------------------------\n"); fprintf(stdout, "system\tsiz\tavm\tfre\tavail\tfi\tfo\tpi\tpo\tfr\tsr\n"); /* Collect the statistics and print them */ rc = display_psize_memory_stats(); fprintf(stdout,"\n"); if (rc == -1) { /* Failed to display statistics properly. Exit safely */ break; } fprintf (stdout," Total memory and paging activity\n"); fprintf(stdout," memory page\n"); fprintf(stdout,"----------------------- ----------------------------------\n"); fprintf(stdout,"avm\tfre\tavail\tpi\tpo\tfr\tsr\tcy\n"); rc = display_total_memory_stats(); fprintf(stdout,"\n------------------------------------------------------------------------------------\n\n"); if (rc == -1) { /* Failed to display statistics properly. Exit safely */ break; } count--; } } if(collect_remote_node_stats) { /* Now disable cluster statistics by calling perfstat_config */ perfstat_config(PERFSTAT_DISABLE|PERFSTAT_CLUSTER_STATS, NULL); } /* Perform cleanup before exiting */ do_cleanup(); return(0); } /* * NAME: do_initialization * This function initializes the data structues. * It also collects initial set of values. * * RETURNS: * On successful completion: * - returns 0. * In case of error * - retruns -1. */ static int do_initialization(void) { int rc; /* Request the total number of available pagesizes in the current system */ if (collect_remote_node_stats) { strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN); nodeid.spec = NODENAME; total_psizes = perfstat_memory_page_node(&nodeid, NULL, NULL, sizeof(perfstat_memory_page_t), 0); } else { total_psizes = perfstat_memory_page(NULL, NULL, sizeof(perfstat_memory_page_t), 0); } if(total_psizes < 1) { perror("do_initialization:" " Unable to retrieve the number of available pagesizes."); return(-1); } /* Allocate sufficient memory */ psize_mem_values = (perfstat_memory_page_t *) malloc(sizeof(perfstat_memory_page_t) * total_psizes); if(psize_mem_values == NULL) { perror("do_initialization: Unable to allocate sufficient" " memory for psize_mem_values buffer."); return(-1); } last_psize_mem_values = (perfstat_memory_page_t *) malloc(sizeof(perfstat_memory_page_t) * total_psizes); if(last_psize_mem_values == NULL) { perror("do_initialization: Unable to allocate sufficient" " memory for last_psize_mem_values buffer."); return(-1); } vmtotal_mem_values = (perfstat_memory_total_t *) malloc(sizeof(perfstat_memory_total_t)); if (vmtotal_mem_values == NULL) { perror("do_initialization: Unable to allocate sufficient" " memory for vmtotal_mem_values buffer."); return(-1); } last_vmtotal_mem_values = (perfstat_memory_total_t *) malloc(sizeof(perfstat_memory_total_t)); if (last_vmtotal_mem_values == NULL) { perror("do_initialization: Unable to allocate sufficient" " memory for last_vmtotal_mem_values buffer."); return(-1); } rc = collect_metrics_pgsz(); if (rc == -1) { perror("do_initialization: Unable to collect data" " for variable page size stats."); return(-1); } save_last_values_pgsz(); rc = collect_metrics_total(); if (rc == -1) { perror("do_initialization: Unable to collect data" " for total vmstat."); return(-1); } save_last_values_total(); return(0) ; } /* * NAME: do_cleanup * This function cleans up the data structues. * * RETURNS: * On successful completion: * - returns 0. * In case of error * - retruns -1. */ static void do_cleanup(void) { if(psize_mem_values) { free(psize_mem_values); } if(last_psize_mem_values) { free(last_psize_mem_values); } if (vmtotal_mem_values) { free(vmtotal_mem_values); } if (last_vmtotal_mem_values) { free(last_vmtotal_mem_values); } return; } /* * NAME: collect_metrics_pgsz * This function retrieves the total number of different pagsizes * currently available and displays memory statistics related to each pagesize. * * RETURNS: * On successful completion: * - returns 0. * In case of error * - retruns -1. */ static int collect_metrics_pgsz(void) { perfstat_psize_t psize; psize.psize = FIRST_PSIZE; if (collect_remote_node_stats) { strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN); nodeid.spec = NODENAME; avail_psizes = perfstat_memory_page_node(&nodeid, &psize, psize_mem_values, sizeof(perfstat_memory_page_t), total_psizes); } else { avail_psizes = perfstat_memory_page(&psize, psize_mem_values, sizeof(perfstat_memory_page_t), total_psizes); } if(avail_psizes < 1) { perror("display_psize_memory_stats: Unable to retrieve memory " "statistics for the available page sizes."); return(-1); } if (!perfstat_cpu_total(NULL, &lcpu_values, sizeof(perfstat_cpu_total_t), 1)) { perror("do_initialization:" " Unable to retrieve the total cpu time."); return(-1); } } /* * NAME: collect_metrics_total * This function retrieves the toatl memory and paging activity information * and displays statistics related same. * * RETURNS: * On successful completion: * - returns 0. * In case of error * - retruns -1. */ static int collect_metrics_total(void) { int rc; if (collect_remote_node_stats) { strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN); nodeid.spec = NODENAME; rc = perfstat_memory_total_node(&nodeid, vmtotal_mem_values, sizeof(perfstat_memory_total_t),1); } else { rc = perfstat_memory_total(NULL,vmtotal_mem_values,sizeof(perfstat_memory_total_t),1); } if (rc != 1) { perror("collect_metrics_total:" " Unable to retrieve paging activity information."); return(-1); } } static void save_last_values_pgsz(void) { perfstat_memory_page_t *tmp_psize_mem_values; /* Save the current memory values as the last ones */ tmp_psize_mem_values = last_psize_mem_values; last_psize_mem_values = psize_mem_values; psize_mem_values = tmp_psize_mem_values; last_lcpu_user = lcpu_values.user; last_lcpu_sys = lcpu_values.sys; last_lcpu_idle = lcpu_values.idle; last_lcpu_wait = lcpu_values.wait; } static void save_last_values_total(void) { last_vmtotal_mem_values = vmtotal_mem_values; } /* * NAME: display_psize_memory_stats * This function retrieves the total number of different pagsizes * currently available and displays memory statistics related to each pagesize. * * RETURNS: * On successful completion: * - returns 0. * In case of error * - retruns -1. */ static int display_psize_memory_stats(void) { perfstat_memory_page_t *itr_psize_mem_values, *itr_last_psize_mem_values; int psize_index; int rc; u_longlong_t delta_pgins, delta_pgouts; u_longlong_t delta_pgspins, delta_pgspouts; u_longlong_t delta_pgsteals, delta_scans; u_longlong_t delta_time; rc = collect_metrics_pgsz(); if(rc == -1) { perror("do_initialization: Unable to allocate sufficient" " memory for last_psize_mem_values buffer."); return(-1); } /*fprintf (stdout, "System\n");*/ itr_psize_mem_values = psize_mem_values; itr_last_psize_mem_values = last_psize_mem_values; for(psize_index = 0; psize_index < avail_psizes; psize_index++) { if(itr_psize_mem_values->psize != itr_last_psize_mem_values->psize) { /* Oops, Unknown error, return with error */ perror("display_psize_memory_stats: curent and last saved values did not match."); return(-1); } /* Print the pagesize as a string */ switch(itr_psize_mem_values->psize) { case PAGE_4K: fprintf(stdout, "4K\t"); break; case PAGE_64K: fprintf(stdout, "64K\t"); break; case PAGE_16M: fprintf(stdout, "16M\t"); break; case PAGE_16G: fprintf(stdout, "16G\t"); break; deafault: /* Oops, Unknown page-size. return error */ perror("display_psize_memory_stats: unknown page-size"); return(-1); } delta_pgins = (itr_psize_mem_values->pgins - itr_last_psize_mem_values->pgins); delta_pgouts = (itr_psize_mem_values->pgouts - itr_last_psize_mem_values->pgouts); delta_pgspins = (itr_psize_mem_values->pgspins - itr_last_psize_mem_values->pgspins); delta_pgspouts = (itr_psize_mem_values->pgspouts - itr_last_psize_mem_values->pgspouts); delta_pgsteals = (itr_psize_mem_values->pgsteals - itr_last_psize_mem_values->pgsteals); delta_scans = (itr_psize_mem_values->scans - itr_last_psize_mem_values->scans); /* calculate total clock tics during the last interval */ delta_time = (lcpu_values.user - last_lcpu_user) + (lcpu_values.sys - last_lcpu_wait) + (lcpu_values.idle - last_lcpu_idle) + (lcpu_values.wait - last_lcpu_wait); /* print the following statistics * -------------------------------------------------------------------------- * siz avm fre avail fi fo pi po fr sr * -------------------------------------------------------------------------- * siz: Number of frames of the specified page size that exist on the * system. * avm: Active virtual pages. * fre: Size of the free list. * avail: Number of pages of the specified page size that are * available without paging out working segments. * fi: File page-ins per second. * fo: File page-outs per second. * pi: Pages paged in from paging space. * po: Pages paged out to paging space. * fr: Pages freed (page replacement). * sr: Pages scanned by page-replacement algorithm. */ fprintf(stdout, "%llu\t", itr_psize_mem_values->real_total); fprintf(stdout, "%llu\t", itr_psize_mem_values->virt_active); fprintf(stdout, "%llu\t", itr_psize_mem_values->real_free); fprintf(stdout, "%llu\t", itr_psize_mem_values->real_avail); fprintf(stdout, "%llu\t", (delta_pgins - delta_pgspins)/delta_time); fprintf(stdout, "%llu\t", (delta_pgouts - delta_pgspouts)/delta_time); fprintf(stdout, "%llu\t", delta_pgspins/delta_time); fprintf(stdout, "%llu\t", delta_pgspouts/delta_time); fprintf(stdout, "%llu\t", delta_pgsteals/delta_time); fprintf(stdout, "%llu\n", delta_scans/delta_time); itr_psize_mem_values++; itr_last_psize_mem_values++; } fprintf(stdout, "\n"); save_last_values_pgsz(); return(0); } /* * NAME: display_total_memory_stats * This function retrieves the total memory and paging activity information * and displays statistics for the same. * * RETURNS: * On successful completion: * - returns 0. * In case of error * - retruns -1. */ static int display_total_memory_stats(void) { int rc; u_longlong_t delta_pgspins, delta_pgspouts; u_longlong_t delta_pgsteals, delta_scans; u_longlong_t delta_time; u_longlong_t delta_cycle; rc = collect_metrics_total(); if(rc == -1) { perror("do_initialization: Unable to allocate sufficient" " memory for last_psize_mem_values buffer."); return(-1); } delta_pgspins = (vmtotal_mem_values->pgspins - last_vmtotal_mem_values->pgspins); delta_pgspouts = (vmtotal_mem_values->pgspouts - last_vmtotal_mem_values->pgspouts); delta_pgsteals = (vmtotal_mem_values->pgsteals - last_vmtotal_mem_values->pgsteals); delta_scans = (vmtotal_mem_values->scans - last_vmtotal_mem_values->scans); delta_cycle = (vmtotal_mem_values->cycles - last_vmtotal_mem_values->cycles); /* calculate total clock tics during the last interval */ delta_time = (lcpu_values.user - last_lcpu_user) + (lcpu_values.sys - last_lcpu_wait) + (lcpu_values.idle - last_lcpu_idle) + (lcpu_values.wait - last_lcpu_wait); /* print the following statistics * ------------------------------------------------------------------ * avm fre avail pi po fr sr cy * ------------------------------------------------------------------ * avm: Active virtual pages. * fre: Size of the free list. * avail: Number of pages (in 4K pagesize) that are * available without paging out working segments. * pi: Pages paged in from paging space. * po: Pages paged out to paging space. * fr: Pages freed (page replacement). * sr: Pages scanned by page-replacement algorithm. * cy: Clock cycles by page-replacement algorithm. */ fprintf(stdout, "%llu\t", vmtotal_mem_values->virt_active); fprintf(stdout, "%llu\t", vmtotal_mem_values->real_free); fprintf(stdout, "%llu\t", vmtotal_mem_values->real_avail); fprintf(stdout, "%llu\t", delta_pgspins/delta_time); fprintf(stdout, "%llu\t", delta_pgspouts/delta_time); fprintf(stdout, "%llu\t", delta_pgsteals/delta_time); fprintf(stdout, "%llu\t", delta_scans/delta_time); fprintf(stdout, "%llu\n", delta_cycle/delta_time); }