15184Sek110237 /*
25184Sek110237 * CDDL HEADER START
35184Sek110237 *
45184Sek110237 * The contents of this file are subject to the terms of the
55184Sek110237 * Common Development and Distribution License (the "License").
65184Sek110237 * You may not use this file except in compliance with the License.
75184Sek110237 *
85184Sek110237 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95184Sek110237 * or http://www.opensolaris.org/os/licensing.
105184Sek110237 * See the License for the specific language governing permissions
115184Sek110237 * and limitations under the License.
125184Sek110237 *
135184Sek110237 * When distributing Covered Code, include this CDDL HEADER in each
145184Sek110237 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155184Sek110237 * If applicable, add the following below this CDDL HEADER, with the
165184Sek110237 * fields enclosed by brackets "[]" replaced with your own identifying
175184Sek110237 * information: Portions Copyright [yyyy] [name of copyright owner]
185184Sek110237 *
195184Sek110237 * CDDL HEADER END
205184Sek110237 */
215184Sek110237 /*
229356SAndrew.W.Wilson@sun.com * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
235184Sek110237 * Use is subject to license terms.
245184Sek110237 */
255184Sek110237
265184Sek110237 #include "config.h"
275184Sek110237
285184Sek110237 #include <stdio.h>
295184Sek110237 #include <fcntl.h>
305184Sek110237 #include <sys/types.h>
315184Sek110237
325184Sek110237 #ifdef HAVE_SYSINFO
335184Sek110237 #include <sys/sysinfo.h>
345184Sek110237 #endif
355184Sek110237
365184Sek110237 #ifdef HAVE_LIBKSTAT
375184Sek110237 #include <kstat.h>
385184Sek110237 #include <sys/cpuvar.h>
395184Sek110237 #endif /* HAVE_LIBKSTAT */
405184Sek110237
415184Sek110237 #include <stdarg.h>
425184Sek110237
435184Sek110237 #include "filebench.h"
445184Sek110237 #include "flowop.h"
455184Sek110237 #include "vars.h"
465184Sek110237 #include "stats.h"
475184Sek110237
485184Sek110237 /*
495184Sek110237 * A set of routines for collecting and dumping various filebench
505184Sek110237 * run statistics.
515184Sek110237 */
525184Sek110237
535184Sek110237 /* Global statistics */
545184Sek110237 static flowstat_t *globalstats = NULL;
555184Sek110237
565184Sek110237 static hrtime_t stats_cputime = 0;
575184Sek110237
585184Sek110237 #ifdef HAVE_LIBKSTAT
595184Sek110237 static kstat_ctl_t *kstatp = NULL;
605184Sek110237 static kstat_t *sysinfo_ksp = NULL;
619356SAndrew.W.Wilson@sun.com static kstat_t **cpu_kstat_list = NULL;
629356SAndrew.W.Wilson@sun.com static int kstat_ncpus = 0;
639356SAndrew.W.Wilson@sun.com
649356SAndrew.W.Wilson@sun.com static int
stats_build_kstat_list(void)659356SAndrew.W.Wilson@sun.com stats_build_kstat_list(void)
669356SAndrew.W.Wilson@sun.com {
679356SAndrew.W.Wilson@sun.com kstat_t *ksp;
689356SAndrew.W.Wilson@sun.com
699356SAndrew.W.Wilson@sun.com kstat_ncpus = 0;
709356SAndrew.W.Wilson@sun.com for (ksp = kstatp->kc_chain; ksp; ksp = ksp->ks_next)
719356SAndrew.W.Wilson@sun.com if (strncmp(ksp->ks_name, "cpu_stat", 8) == 0)
729356SAndrew.W.Wilson@sun.com kstat_ncpus++;
739356SAndrew.W.Wilson@sun.com
749356SAndrew.W.Wilson@sun.com if ((cpu_kstat_list = (kstat_t **)
759356SAndrew.W.Wilson@sun.com malloc(kstat_ncpus * sizeof (kstat_t *))) == NULL) {
769356SAndrew.W.Wilson@sun.com filebench_log(LOG_ERROR, "malloc failed");
779356SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR);
789356SAndrew.W.Wilson@sun.com }
799356SAndrew.W.Wilson@sun.com
809356SAndrew.W.Wilson@sun.com kstat_ncpus = 0;
819356SAndrew.W.Wilson@sun.com for (ksp = kstatp->kc_chain; ksp; ksp = ksp->ks_next)
829356SAndrew.W.Wilson@sun.com if (strncmp(ksp->ks_name, "cpu_stat", 8) == 0 &&
839356SAndrew.W.Wilson@sun.com kstat_read(kstatp, ksp, NULL) != -1)
849356SAndrew.W.Wilson@sun.com cpu_kstat_list[kstat_ncpus++] = ksp;
859356SAndrew.W.Wilson@sun.com
869356SAndrew.W.Wilson@sun.com if (kstat_ncpus == 0) {
879356SAndrew.W.Wilson@sun.com filebench_log(LOG_ERROR,
889356SAndrew.W.Wilson@sun.com "kstats can't find any cpu statistics");
899356SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR);
909356SAndrew.W.Wilson@sun.com }
919356SAndrew.W.Wilson@sun.com
929356SAndrew.W.Wilson@sun.com return (FILEBENCH_OK);
939356SAndrew.W.Wilson@sun.com }
949356SAndrew.W.Wilson@sun.com
959356SAndrew.W.Wilson@sun.com static int
stats_kstat_update(void)969356SAndrew.W.Wilson@sun.com stats_kstat_update(void)
979356SAndrew.W.Wilson@sun.com {
989356SAndrew.W.Wilson@sun.com if (kstatp == NULL) {
999356SAndrew.W.Wilson@sun.com if ((kstatp = kstat_open()) == (kstat_ctl_t *)NULL) {
1009356SAndrew.W.Wilson@sun.com filebench_log(LOG_ERROR, "Cannot read kstats");
1019356SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR);
1029356SAndrew.W.Wilson@sun.com }
1039356SAndrew.W.Wilson@sun.com }
1049356SAndrew.W.Wilson@sun.com
1059356SAndrew.W.Wilson@sun.com /* get the sysinfo kstat */
1069356SAndrew.W.Wilson@sun.com if (sysinfo_ksp == NULL)
1079356SAndrew.W.Wilson@sun.com sysinfo_ksp = kstat_lookup(kstatp, "unix", 0, "sysinfo");
1089356SAndrew.W.Wilson@sun.com
1099356SAndrew.W.Wilson@sun.com /* get per cpu kstats, if necessary */
1109356SAndrew.W.Wilson@sun.com if (cpu_kstat_list == NULL) {
1119356SAndrew.W.Wilson@sun.com
1129356SAndrew.W.Wilson@sun.com /* Initialize the array of cpu kstat pointers */
1139356SAndrew.W.Wilson@sun.com if (stats_build_kstat_list() == FILEBENCH_ERROR)
1149356SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR);
1159356SAndrew.W.Wilson@sun.com
1169356SAndrew.W.Wilson@sun.com } else if (kstat_chain_update(kstatp) != 0) {
1179356SAndrew.W.Wilson@sun.com
1189356SAndrew.W.Wilson@sun.com /* free up current array of kstat ptrs and get new one */
1199356SAndrew.W.Wilson@sun.com free((void *)cpu_kstat_list);
1209356SAndrew.W.Wilson@sun.com if (stats_build_kstat_list() == FILEBENCH_ERROR)
1219356SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR);
1229356SAndrew.W.Wilson@sun.com }
1239356SAndrew.W.Wilson@sun.com
1249356SAndrew.W.Wilson@sun.com return (FILEBENCH_OK);
1259356SAndrew.W.Wilson@sun.com }
1265184Sek110237
1275184Sek110237 /*
1285184Sek110237 * Uses the kstat library or, if it is not available, the /proc/stat file
1295184Sek110237 * to obtain cpu statistics. Collects statistics for each cpu, initializes
1305184Sek110237 * a local pointer to the sysinfo kstat, and returns the sum of user and
1315184Sek110237 * kernel time for all the cpus.
1325184Sek110237 */
1336212Saw148015 static fbint_t
kstats_read_cpu(void)1345184Sek110237 kstats_read_cpu(void)
1355184Sek110237 {
136*9513SAndrew.W.Wilson@sun.com u_longlong_t cputime_states[CPU_STATES];
137*9513SAndrew.W.Wilson@sun.com hrtime_t cputime;
138*9513SAndrew.W.Wilson@sun.com int i;
1395184Sek110237
1405184Sek110237 /*
1415184Sek110237 * Per-CPU statistics
1425184Sek110237 */
1435184Sek110237
1449356SAndrew.W.Wilson@sun.com if (stats_kstat_update() == FILEBENCH_ERROR)
1455184Sek110237 return (0);
1465184Sek110237
1475184Sek110237 /* Sum across all CPUs */
1485184Sek110237 (void) memset(&cputime_states, 0, sizeof (cputime_states));
1499356SAndrew.W.Wilson@sun.com for (i = 0; i < kstat_ncpus; i++) {
1505184Sek110237 cpu_stat_t cpu_stats;
1515184Sek110237 int j;
1525184Sek110237
1539356SAndrew.W.Wilson@sun.com (void) kstat_read(kstatp, cpu_kstat_list[i],
1545184Sek110237 (void *) &cpu_stats);
1555184Sek110237 for (j = 0; j < CPU_STATES; j++)
1565184Sek110237 cputime_states[j] += cpu_stats.cpu_sysinfo.cpu[j];
1575184Sek110237 }
1585184Sek110237
1595184Sek110237 cputime = cputime_states[CPU_KERNEL] + cputime_states[CPU_USER];
1605184Sek110237
1615184Sek110237 return (10000000LL * cputime);
1625184Sek110237 }
1635184Sek110237 #else /* HAVE_LIBKSTAT */
1645184Sek110237 #ifdef HAVE_PROC_STAT
1655184Sek110237 static FILE *statfd = 0;
1666212Saw148015 fbint_t
kstats_read_cpu(void)1675184Sek110237 kstats_read_cpu(void)
1685184Sek110237 {
1695184Sek110237 /*
1705184Sek110237 * Linux provides system wide statistics in /proc/stat
1715184Sek110237 * The entry for cpu is
1725184Sek110237 * cpu 1636 67 1392 208671 5407 20 12
1735184Sek110237 * cpu0 626 8 997 104476 2499 7 7
1745184Sek110237 * cpu1 1010 58 395 104195 2907 13 5
1755184Sek110237 *
1765184Sek110237 * The number of jiffies (1/100ths of a second) that the
1775184Sek110237 * system spent in user mode, user mode with low priority
1785184Sek110237 * (nice), system mode, and the idle task, respectively.
1795184Sek110237 */
1805184Sek110237 unsigned int user, nice, system;
1815184Sek110237 char cpu[128]; /* placeholder to read "cpu" */
1825184Sek110237 if (statfd == 0) {
1835184Sek110237 statfd = fopen("/proc/stat", "r");
1845184Sek110237 if (statfd < 0) {
1855184Sek110237 filebench_log(LOG_ERROR, "Cannot open /proc/stat");
1865184Sek110237 return (-1);
1875184Sek110237 }
1885184Sek110237 }
1895184Sek110237 if (fscanf(statfd, "%s %u %u %u", cpu, &user, &nice, &system) < 0) {
1905184Sek110237 filebench_log(LOG_ERROR, "Cannot read /proc/stat");
1915184Sek110237 return (-1);
1925184Sek110237 }
1935184Sek110237 /* convert jiffies to nanosecs */
1945184Sek110237 return ((user+nice+system)*1000000);
1955184Sek110237 }
1965184Sek110237
1975184Sek110237 #else /* HAVE_PROC_STAT */
1986212Saw148015 fbint_t
kstats_read_cpu(void)1995184Sek110237 kstats_read_cpu(void)
2005184Sek110237 {
2015184Sek110237 return (0);
2025184Sek110237 }
2035184Sek110237 #endif
2045184Sek110237 #endif /* HAVE_LIBKSTAT */
2055184Sek110237
2065184Sek110237 /*
2075184Sek110237 * Returns the net cpu time used since the beginning of the run.
2085184Sek110237 * Just calls kstat_read_cpu() and subtracts stats_cputime which
2095184Sek110237 * is set at the beginning of the filebench run.
2105184Sek110237 */
2115184Sek110237 static hrtime_t
kstats_read_cpu_relative(void)2125184Sek110237 kstats_read_cpu_relative(void)
2135184Sek110237 {
2145184Sek110237 hrtime_t cputime;
2155184Sek110237
2165184Sek110237 cputime = kstats_read_cpu();
2175184Sek110237 return (cputime - stats_cputime);
2185184Sek110237 }
2195184Sek110237
2205184Sek110237 /*
2215184Sek110237 * IO Overhead CPU is the amount of CPU that is incurred running
2225184Sek110237 * the benchmark infrastructure.
2235184Sek110237 *
2245184Sek110237 * It is computed as the sum of micro-state cpu time for each
2255184Sek110237 * thread around the op being tested.
2265184Sek110237 *
2275184Sek110237 * Overhead time is computed for each flow.
2285184Sek110237 *
2295184Sek110237 * System overhead is computed as the overhead for I/O flows
2305184Sek110237 * plus all other time running non-io related flowops
2315184Sek110237 *
2325184Sek110237 */
2335184Sek110237
2345184Sek110237 /*
2355184Sek110237 * Computes and returns the overhead CPU time attibutable to
2365184Sek110237 * IO type flowops.
2375184Sek110237 */
2385184Sek110237 static hrtime_t
io_stats_ohead(void)2395184Sek110237 io_stats_ohead(void)
2405184Sek110237 {
2415184Sek110237 flowstat_t *iostat = &globalstats[FLOW_TYPE_IO];
2425184Sek110237 flowstat_t *aiostat = &globalstats[FLOW_TYPE_AIO];
2435184Sek110237 flowstat_t *glstat = &globalstats[FLOW_TYPE_GLOBAL];
2445184Sek110237
2455184Sek110237 filebench_log(LOG_DEBUG_NEVER,
2466286Saw148015 "Computing overhead as %llu + %llu - %llu - %llu",
2476286Saw148015 (u_longlong_t)glstat->fs_mstate[FLOW_MSTATE_OHEAD],
2486286Saw148015 (u_longlong_t)glstat->fs_mstate[FLOW_MSTATE_CPU],
2496286Saw148015 (u_longlong_t)iostat->fs_mstate[FLOW_MSTATE_CPU],
2506286Saw148015 (u_longlong_t)aiostat->fs_mstate[FLOW_MSTATE_CPU]);
2515184Sek110237
2525184Sek110237 return ((glstat->fs_mstate[FLOW_MSTATE_OHEAD] +
2535184Sek110237 glstat->fs_mstate[FLOW_MSTATE_CPU] -
2545184Sek110237 iostat->fs_mstate[FLOW_MSTATE_CPU] -
2555184Sek110237 aiostat->fs_mstate[FLOW_MSTATE_CPU]));
2565184Sek110237 }
2575184Sek110237
2585184Sek110237 /*
2595184Sek110237 * Returns the total overhead CPU time.
2605184Sek110237 */
2615184Sek110237 static hrtime_t
gl_stats_ohead(void)2625184Sek110237 gl_stats_ohead(void)
2635184Sek110237 {
2645184Sek110237 flowstat_t *glstat = &globalstats[FLOW_TYPE_GLOBAL];
2655184Sek110237
2665184Sek110237 return (glstat->fs_mstate[FLOW_MSTATE_OHEAD]);
2675184Sek110237 }
2685184Sek110237
2695184Sek110237 /*
2706212Saw148015 * Places the value represented by "name" into the var_val.integer field of the
2715184Sek110237 * supplied var_t. Compares the supplied "name" with a set of predefined
2725184Sek110237 * names and calculates the value from the appropriate globalstats field(s).
2735184Sek110237 */
2745184Sek110237 var_t *
stats_findvar(var_t * var,char * name)2755184Sek110237 stats_findvar(var_t *var, char *name)
2765184Sek110237 {
2775184Sek110237 flowstat_t *iostat = &globalstats[FLOW_TYPE_IO];
2785184Sek110237 flowstat_t *aiostat = &globalstats[FLOW_TYPE_AIO];
2795184Sek110237 flowstat_t *glstat = &globalstats[FLOW_TYPE_GLOBAL];
2805184Sek110237
2815184Sek110237 filebench_log(LOG_DEBUG_IMPL, "reading stats %s", name);
2825184Sek110237
2835184Sek110237 if (globalstats == NULL)
2845184Sek110237 globalstats = malloc(FLOW_TYPES * sizeof (flowstat_t));
2855184Sek110237
2865184Sek110237 if (strcmp(name, "iocount") == 0) {
2876212Saw148015 fbint_t stat;
2886212Saw148015
2896212Saw148015 stat = iostat->fs_count + aiostat->fs_count;
2906212Saw148015 VAR_SET_INT(var, stat);
2916286Saw148015 filebench_log(LOG_DEBUG_IMPL, "reading stats %s = %llu",
2926286Saw148015 name, (u_longlong_t)stat);
2935184Sek110237 return (var);
2945184Sek110237 }
2955184Sek110237
2965184Sek110237 if (strcmp(name, "iorate") == 0) {
2976212Saw148015 fbint_t stat;
2986212Saw148015
2995184Sek110237 /* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
3006212Saw148015 stat = (iostat->fs_count + aiostat->fs_count) /
3015184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS);
3026212Saw148015 VAR_SET_INT(var, stat);
3035184Sek110237 return (var);
3045184Sek110237 }
3055184Sek110237
3065184Sek110237
3075184Sek110237 if (strcmp(name, "ioreadrate") == 0) {
3086212Saw148015 fbint_t stat;
3096212Saw148015
3105184Sek110237 /* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
3116212Saw148015 stat = (iostat->fs_rcount + aiostat->fs_rcount) /
3125184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS);
3136212Saw148015 VAR_SET_INT(var, stat);
3145184Sek110237 return (var);
3155184Sek110237 }
3165184Sek110237
3175184Sek110237
3185184Sek110237 if (strcmp(name, "iowriterate") == 0) {
3196212Saw148015 fbint_t stat;
3206212Saw148015
3215184Sek110237 /* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
3226212Saw148015 stat = (iostat->fs_wcount + aiostat->fs_wcount) /
3235184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS);
3246212Saw148015 VAR_SET_INT(var, stat);
3255184Sek110237 return (var);
3265184Sek110237 }
3275184Sek110237
3285184Sek110237
3295184Sek110237 if (strcmp(name, "iobandwidth") == 0) {
3306212Saw148015 fbint_t stat;
3316212Saw148015
3325184Sek110237 /* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
3336212Saw148015 stat =
3345184Sek110237 ((iostat->fs_bytes + aiostat->fs_bytes) / (1024 * 1024)) /
3355184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS);
3366212Saw148015 VAR_SET_INT(var, stat);
3375184Sek110237 return (var);
3385184Sek110237 }
3395184Sek110237
3405184Sek110237 if (strcmp(name, "iolatency") == 0) {
3416212Saw148015 fbint_t stat;
3426212Saw148015
3436212Saw148015 stat = iostat->fs_count ? iostat->fs_mstate[FLOW_MSTATE_LAT] /
3445184Sek110237 (iostat->fs_count * 1000UL) : 0;
3456212Saw148015 VAR_SET_INT(var, stat);
3465184Sek110237 return (var);
3475184Sek110237 }
3485184Sek110237
3495184Sek110237 if (strcmp(name, "iocpu") == 0) {
3506212Saw148015 fbint_t stat;
3516212Saw148015
3526212Saw148015 stat = (iostat->fs_count + aiostat->fs_count) ?
3535184Sek110237 (iostat->fs_mstate[FLOW_MSTATE_CPU] +
3545184Sek110237 aiostat->fs_mstate[FLOW_MSTATE_CPU]) / ((iostat->fs_count +
3555184Sek110237 aiostat->fs_count) * 1000UL) : 0;
3566212Saw148015 VAR_SET_INT(var, stat);
3575184Sek110237 return (var);
3585184Sek110237 }
3595184Sek110237
3605184Sek110237
3615184Sek110237 if (strcmp(name, "oheadcpu") == 0) {
3626212Saw148015 fbint_t stat;
3636212Saw148015
3646212Saw148015 stat = (iostat->fs_count + aiostat->fs_count) ?
3655184Sek110237 io_stats_ohead() / ((iostat->fs_count +
3665184Sek110237 aiostat->fs_count) * 1000UL) : 0;
3676212Saw148015 VAR_SET_INT(var, stat);
3685184Sek110237 return (var);
3695184Sek110237 }
3705184Sek110237
3715184Sek110237 if (strcmp(name, "iowait") == 0) {
3726212Saw148015 fbint_t stat;
3736212Saw148015
3746212Saw148015 stat = iostat->fs_count ?
3755184Sek110237 iostat->fs_mstate[FLOW_MSTATE_WAIT] /
3765184Sek110237 (iostat->fs_count * 1000UL) : 0;
3776212Saw148015 VAR_SET_INT(var, stat);
3785184Sek110237 return (var);
3795184Sek110237 }
3805184Sek110237
3815184Sek110237 if (strcmp(name, "syscpu") == 0) {
3826212Saw148015 fbint_t stat;
3836212Saw148015
3845184Sek110237 /* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
3856212Saw148015 stat = glstat->fs_syscpu / 1000.0;
3866212Saw148015 VAR_SET_INT(var, stat);
3875184Sek110237 return (var);
3885184Sek110237 }
3895184Sek110237
3905184Sek110237 if (strcmp(name, "iocpusys") == 0) {
3916212Saw148015 fbint_t stat;
3926212Saw148015
3936212Saw148015 stat = (iostat->fs_count + aiostat->fs_count) ?
3945184Sek110237 iostat->fs_syscpu / ((iostat->fs_count +
3955184Sek110237 aiostat->fs_count) * 1000UL) : 0;
3965184Sek110237
3976212Saw148015 VAR_SET_INT(var, stat);
3985184Sek110237 return (var);
3995184Sek110237 }
4005184Sek110237
4015184Sek110237 filebench_log(LOG_DEBUG_IMPL,
4025184Sek110237 "error reading stats %s", name);
4035184Sek110237
4045184Sek110237 return (NULL);
4055184Sek110237 }
4065184Sek110237
4075184Sek110237 /*
4085184Sek110237 * Initializes the static variable "stats_cputime" with the
4095184Sek110237 * current cpu time, for use by kstats_read_cpu_relative.
4105184Sek110237 */
4115184Sek110237 void
stats_init(void)4125184Sek110237 stats_init(void)
4135184Sek110237 {
4145184Sek110237 #if defined(HAVE_LIBKSTAT) || defined(LINUX_PORT)
4155184Sek110237 stats_cputime = kstats_read_cpu();
4165184Sek110237 #else
4175184Sek110237 stats_cputime = 0;
4185184Sek110237 #endif /* HAVE_LIBKSTAT */
4195184Sek110237 }
4205184Sek110237
4215184Sek110237 /*
4225184Sek110237 * Add a flowstat b to a, leave sum in a.
4235184Sek110237 */
4245184Sek110237 static void
stats_add(flowstat_t * a,flowstat_t * b)4255184Sek110237 stats_add(flowstat_t *a, flowstat_t *b)
4265184Sek110237 {
4275184Sek110237 int i;
4285184Sek110237
4295184Sek110237 a->fs_count += b->fs_count;
4305184Sek110237 a->fs_rcount += b->fs_rcount;
4315184Sek110237 a->fs_wcount += b->fs_wcount;
4325184Sek110237 a->fs_bytes += b->fs_bytes;
4335184Sek110237 a->fs_rbytes += b->fs_rbytes;
4345184Sek110237 a->fs_wbytes += b->fs_wbytes;
4355184Sek110237
4365184Sek110237 for (i = 0; i < FLOW_MSTATES; i++)
4375184Sek110237 a->fs_mstate[i] += b->fs_mstate[i];
4385184Sek110237 }
4395184Sek110237
4405184Sek110237 /*
4415184Sek110237 * Takes a "snapshot" of the global statistics. Actually, it calculates
4425184Sek110237 * them from the local statistics maintained by each flowop.
4435184Sek110237 * First the routine pauses filebench, then rolls the statistics for
4445184Sek110237 * each flowop into its associated FLOW_MASTER flowop.
4455184Sek110237 * Next all the FLOW_MASTER flowops' statistics are written
4465184Sek110237 * to the log file followed by the global totals. Then filebench
4475184Sek110237 * operation is allowed to resume.
4485184Sek110237 */
4495184Sek110237 void
stats_snap(void)4505184Sek110237 stats_snap(void)
4515184Sek110237 {
4525184Sek110237 flowstat_t *iostat = &globalstats[FLOW_TYPE_IO];
4535184Sek110237 flowstat_t *aiostat = &globalstats[FLOW_TYPE_AIO];
4545184Sek110237 flowstat_t *glstat = &globalstats[FLOW_TYPE_GLOBAL];
4555184Sek110237 hrtime_t cputime;
4565184Sek110237 flowop_t *flowop;
4575184Sek110237 char *str;
4585184Sek110237
4595184Sek110237 if (globalstats == NULL) {
4605184Sek110237 filebench_log(LOG_ERROR,
4615184Sek110237 "'stats snap' called before 'stats clear'");
4625184Sek110237 return;
4635184Sek110237 }
4645184Sek110237
4656084Saw148015 /* don't print out if run ended in error */
4666391Saw148015 if (filebench_shm->shm_f_abort == FILEBENCH_ABORT_ERROR) {
4676084Saw148015 filebench_log(LOG_ERROR,
4686084Saw148015 "NO VALID RESULTS! FileBench run terminated prematurely");
4696084Saw148015 return;
4706084Saw148015 }
4716084Saw148015
4725184Sek110237 globalstats->fs_etime = gethrtime();
4735184Sek110237
4745184Sek110237 filebench_log(LOG_DEBUG_SCRIPT, "Stats period = %ds",
4755184Sek110237 (globalstats->fs_etime - globalstats->fs_stime) / 1000000000);
4765184Sek110237
4775184Sek110237 /* Freeze statistics during update */
4786391Saw148015 filebench_shm->shm_bequiet = 1;
4795184Sek110237
4806391Saw148015 flowop = filebench_shm->shm_flowoplist;
4815184Sek110237 while (flowop) {
4825184Sek110237 flowop_t *flowop_master;
4835184Sek110237
4846212Saw148015 if (flowop->fo_instance <= FLOW_DEFINITION) {
4855184Sek110237 flowop = flowop->fo_next;
4865184Sek110237 continue;
4875184Sek110237 }
4885184Sek110237
4896212Saw148015 flowop_master = flowop_find_one(flowop->fo_name, FLOW_MASTER);
4905184Sek110237
4915184Sek110237 /* Roll up per-flowop into global stats */
4925184Sek110237 stats_add(&globalstats[flowop->fo_type],
4935184Sek110237 &flowop->fo_stats);
4945184Sek110237 stats_add(&globalstats[FLOW_TYPE_GLOBAL],
4955184Sek110237 &flowop->fo_stats);
4965184Sek110237
4975184Sek110237 if (flowop_master && IS_FLOW_ACTIVE(flowop)) {
4985184Sek110237 flowop_master->fo_stats.fs_active++;
4995184Sek110237 }
5005184Sek110237
5015184Sek110237 if (flowop_master) {
5025184Sek110237 /* Roll up per-flow stats into master */
5035184Sek110237 flowop_master->fo_stats.fs_children++;
5045184Sek110237 stats_add(&flowop_master->fo_stats, &flowop->fo_stats);
5055184Sek110237 } else {
5065184Sek110237 filebench_log(LOG_DEBUG_NEVER,
5075184Sek110237 "flowop_stats could not find %s",
5085184Sek110237 flowop->fo_name);
5095184Sek110237 }
5105184Sek110237
5115184Sek110237 filebench_log(LOG_DEBUG_SCRIPT,
5125184Sek110237 "flowop %-20s-%4d - %5d ops, %5.1lf, ops/s %5.1lfmb/s "
5135184Sek110237 "%8.3fms/op",
5145184Sek110237 flowop->fo_name,
5155184Sek110237 flowop->fo_instance,
5165184Sek110237 flowop->fo_stats.fs_count,
5175184Sek110237 flowop->fo_stats.fs_count /
5185184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
5195184Sek110237 (flowop->fo_stats.fs_bytes / (1024 * 1024)) /
5205184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
5215184Sek110237 flowop->fo_stats.fs_count ?
5225184Sek110237 flowop->fo_stats.fs_mstate[FLOW_MSTATE_LAT] /
5235184Sek110237 (flowop->fo_stats.fs_count * 1000000.0) : 0);
5245184Sek110237
5255184Sek110237 flowop = flowop->fo_next;
5265184Sek110237
5275184Sek110237 }
5285184Sek110237
5295184Sek110237 #if defined(HAVE_LIBKSTAT) || defined(LINUX_PORT)
5305184Sek110237 cputime = kstats_read_cpu_relative();
5315184Sek110237 #endif /* HAVE_LIBKSTAT */
5325184Sek110237
5335184Sek110237 filebench_log(LOG_DEBUG_IMPL,
5346286Saw148015 "cputime = %llu, ohead = %llu",
5356286Saw148015 (u_longlong_t)(cputime / 1000000000),
5366286Saw148015 (u_longlong_t)(io_stats_ohead() / 1000000000));
5375184Sek110237 iostat->fs_syscpu =
5385184Sek110237 (cputime > io_stats_ohead()) ?
5395184Sek110237 (cputime - io_stats_ohead()) : 0;
5405184Sek110237 glstat->fs_syscpu =
5415184Sek110237 (cputime > gl_stats_ohead()) ?
5425184Sek110237 (cputime - gl_stats_ohead()) : 0;
5435184Sek110237
5445184Sek110237
5456391Saw148015 flowop = filebench_shm->shm_flowoplist;
5465184Sek110237 str = malloc(1048576);
5476613Sek110237 *str = '\0';
5485184Sek110237 (void) strcpy(str, "Per-Operation Breakdown\n");
5495184Sek110237 while (flowop) {
5505184Sek110237 char line[1024];
5515184Sek110237
5525184Sek110237 if (flowop->fo_instance != FLOW_MASTER) {
5535184Sek110237 flowop = flowop->fo_next;
5545184Sek110237 continue;
5555184Sek110237 }
5565184Sek110237
5575184Sek110237 (void) snprintf(line, sizeof (line), "%-20s %8.0lfops/s "
5585184Sek110237 "%5.1lfmb/s %8.1fms/op %8.0fus/op-cpu\n",
5595184Sek110237 flowop->fo_name,
5605184Sek110237 flowop->fo_stats.fs_count /
5615184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
5625184Sek110237 (flowop->fo_stats.fs_bytes / (1024 * 1024)) /
5635184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
5645184Sek110237 flowop->fo_stats.fs_count ?
5655184Sek110237 flowop->fo_stats.fs_mstate[FLOW_MSTATE_LAT] /
5665184Sek110237 (flowop->fo_stats.fs_count * 1000000.0) : 0,
5675184Sek110237 flowop->fo_stats.fs_count ?
5685184Sek110237 flowop->fo_stats.fs_mstate[FLOW_MSTATE_CPU] /
5695184Sek110237 (flowop->fo_stats.fs_count * 1000.0) : 0);
5705184Sek110237 (void) strcat(str, line);
5715184Sek110237
5725184Sek110237 flowop = flowop->fo_next;
5735184Sek110237 }
5745184Sek110237
5755184Sek110237 filebench_log(LOG_INFO, "%s", str);
5765184Sek110237 free(str);
5775184Sek110237
5785184Sek110237 filebench_log(LOG_INFO,
5797736SAndrew.W.Wilson@sun.com "\nIO Summary: %5d ops, %5.1lf ops/s, (%0.0lf/%0.0lf r/w) "
5805184Sek110237 "%5.1lfmb/s, %6.0fus cpu/op, %5.1fms latency",
5815184Sek110237 iostat->fs_count + aiostat->fs_count,
5825184Sek110237 (iostat->fs_count + aiostat->fs_count) /
5835184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
5845184Sek110237 (iostat->fs_rcount + aiostat->fs_rcount) /
5855184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
5865184Sek110237 (iostat->fs_wcount + aiostat->fs_wcount) /
5875184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
5885184Sek110237 ((iostat->fs_bytes + aiostat->fs_bytes) / (1024 * 1024)) /
5895184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
5905184Sek110237 (iostat->fs_rcount + iostat->fs_wcount +
5915184Sek110237 aiostat->fs_rcount + aiostat->fs_wcount) ?
5925184Sek110237 (iostat->fs_syscpu / 1000.0) /
5935184Sek110237 (iostat->fs_rcount + iostat->fs_wcount +
5945184Sek110237 aiostat->fs_rcount + aiostat->fs_wcount) : 0,
5955184Sek110237 (iostat->fs_rcount + iostat->fs_wcount) ?
5965184Sek110237 iostat->fs_mstate[FLOW_MSTATE_LAT] /
5975184Sek110237 ((iostat->fs_rcount + iostat->fs_wcount) * 1000000.0) : 0);
5985184Sek110237
5995184Sek110237
6006391Saw148015 filebench_shm->shm_bequiet = 0;
6015184Sek110237 }
6025184Sek110237
6035184Sek110237 /*
6045184Sek110237 * Dumps the per-operation statistics and global statistics to the dump file.
6055184Sek110237 */
6065184Sek110237 void
stats_dump(char * filename)6075184Sek110237 stats_dump(char *filename)
6085184Sek110237 {
6095184Sek110237 flowstat_t *iostat = &globalstats[FLOW_TYPE_IO];
6105184Sek110237 flowstat_t *aiostat = &globalstats[FLOW_TYPE_AIO];
6115184Sek110237 flowop_t *flowop;
6125184Sek110237
6136084Saw148015 /* don't dump stats if run ended in error */
6146391Saw148015 if (filebench_shm->shm_f_abort == FILEBENCH_ABORT_ERROR)
6156084Saw148015 return;
6166084Saw148015
6176391Saw148015 (void) strcpy(filebench_shm->shm_dump_filename, filename);
6185184Sek110237
6195184Sek110237 filebench_log(LOG_INFO, "in statsdump %s", filename);
6205184Sek110237
6216391Saw148015 if (filebench_shm->shm_dump_fd > 0) {
6226391Saw148015 (void) close(filebench_shm->shm_dump_fd);
6236391Saw148015 filebench_shm->shm_dump_fd = -1;
6245184Sek110237 }
6255184Sek110237
6265184Sek110237 filebench_log(LOG_DUMP, "Flowop totals:");
6275184Sek110237
6286391Saw148015 flowop = filebench_shm->shm_flowoplist;
6295184Sek110237 while (flowop) {
6305184Sek110237
6315184Sek110237 if (flowop->fo_instance != FLOW_MASTER) {
6325184Sek110237 flowop = flowop->fo_next;
6335184Sek110237 continue;
6345184Sek110237 }
6355184Sek110237
6365184Sek110237 filebench_log(LOG_DUMP,
6375184Sek110237 "%-20s %8.0lfops/s %5.1lfmb/s "
6385184Sek110237 "%8.1fms/op %8.0fus/op-cpu",
6395184Sek110237 flowop->fo_name,
6405184Sek110237 flowop->fo_stats.fs_count /
6415184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
6425184Sek110237 (flowop->fo_stats.fs_bytes / (1024 * 1024)) /
6435184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
6445184Sek110237 flowop->fo_stats.fs_count ?
6455184Sek110237 flowop->fo_stats.fs_mstate[FLOW_MSTATE_LAT] /
6465184Sek110237 (flowop->fo_stats.fs_count * 1000000.0) : 0,
6475184Sek110237 flowop->fo_stats.fs_count ?
6485184Sek110237 flowop->fo_stats.fs_mstate[FLOW_MSTATE_CPU] /
6495184Sek110237 (flowop->fo_stats.fs_count * 1000.0) : 0);
6505184Sek110237
6515184Sek110237 flowop = flowop->fo_next;
6525184Sek110237 }
6535184Sek110237
6545184Sek110237 filebench_log(LOG_DUMP, "");
6555184Sek110237 filebench_log(LOG_DUMP,
6565184Sek110237 "IO Summary: %8d ops %8.1lf ops/s, %8.0lf/%0.0lf r/w"
6575184Sek110237 "%8.1lfmb/s, %8.0fuscpu/op",
6585184Sek110237
6595184Sek110237 iostat->fs_count + aiostat->fs_count,
6605184Sek110237 (iostat->fs_count + aiostat->fs_count) /
6615184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
6625184Sek110237
6635184Sek110237 (iostat->fs_rcount + aiostat->fs_rcount) /
6645184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
6655184Sek110237
6665184Sek110237 (iostat->fs_wcount + aiostat->fs_wcount) /
6675184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
6685184Sek110237
6695184Sek110237 ((iostat->fs_bytes + aiostat->fs_bytes) / (1024 * 1024)) /
6705184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
6715184Sek110237
6725184Sek110237 (iostat->fs_rcount + iostat->fs_wcount +
6735184Sek110237 aiostat->fs_rcount + aiostat->fs_wcount) ?
6745184Sek110237 (iostat->fs_syscpu / 1000.0) /
6755184Sek110237 (iostat->fs_rcount + iostat->fs_wcount +
6765184Sek110237 aiostat->fs_rcount + aiostat->fs_wcount) : 0);
6775184Sek110237 }
6785184Sek110237
6795184Sek110237 /*
6805184Sek110237 * Same as stats_dump, but in xml format.
6815184Sek110237 */
6825184Sek110237 void
stats_xmldump(char * filename)6835184Sek110237 stats_xmldump(char *filename)
6845184Sek110237 {
6855184Sek110237 flowstat_t *iostat = &globalstats[FLOW_TYPE_IO];
6865184Sek110237 flowstat_t *aiostat = &globalstats[FLOW_TYPE_AIO];
6875184Sek110237 flowop_t *flowop;
6885184Sek110237
6896084Saw148015 /* don't dump stats if run ended in error */
6906391Saw148015 if (filebench_shm->shm_f_abort == FILEBENCH_ABORT_ERROR)
6916084Saw148015 return;
6926084Saw148015
6936391Saw148015 (void) strcpy(filebench_shm->shm_dump_filename, filename);
6945184Sek110237
6956391Saw148015 if (filebench_shm->shm_dump_fd > 0) {
6966391Saw148015 (void) close(filebench_shm->shm_dump_fd);
6976391Saw148015 filebench_shm->shm_dump_fd = -1;
6985184Sek110237 }
6995184Sek110237
7005184Sek110237 filebench_log(LOG_DUMP, "<stat_doc name=\"Filebench Workload\">");
7015184Sek110237 filebench_log(LOG_DUMP, "<stat_group name=\"Flowop totals\">");
7025184Sek110237 filebench_log(LOG_DUMP, "<cell_list>");
7035184Sek110237
7046391Saw148015 flowop = filebench_shm->shm_flowoplist;
7055184Sek110237 while (flowop) {
7065184Sek110237 if (flowop->fo_instance != FLOW_MASTER) {
7075184Sek110237 flowop = flowop->fo_next;
7085184Sek110237 continue;
7095184Sek110237 }
7105184Sek110237
7115184Sek110237 filebench_log(LOG_DUMP, "<cell>%0.0lf</cell>",
7125184Sek110237 flowop->fo_stats.fs_count /
7135184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS));
7145184Sek110237 filebench_log(LOG_DUMP, "<cell>%0.1lf</cell>",
7155184Sek110237 (flowop->fo_stats.fs_bytes / (1024 * 1024)) /
7165184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS));
7175184Sek110237 filebench_log(LOG_DUMP, "<cell>%0.1lf</cell>",
7185184Sek110237 flowop->fo_stats.fs_count ?
7195184Sek110237 flowop->fo_stats.fs_mstate[FLOW_MSTATE_LAT] /
7205184Sek110237 (flowop->fo_stats.fs_count * 1000000.0) : 0);
7215184Sek110237 filebench_log(LOG_DUMP, "<cell>%0.0lf</cell>",
7225184Sek110237 flowop->fo_stats.fs_count ?
7235184Sek110237 flowop->fo_stats.fs_mstate[FLOW_MSTATE_CPU] /
7245184Sek110237 (flowop->fo_stats.fs_count * 1000.0) : 0);
7255184Sek110237
7265184Sek110237 flowop = flowop->fo_next;
7275184Sek110237 }
7285184Sek110237 filebench_log(LOG_DUMP, "</cell_list>");
7295184Sek110237
7305184Sek110237 filebench_log(LOG_DUMP, "<dim_list>");
7315184Sek110237 filebench_log(LOG_DUMP, "<dim>");
7325184Sek110237 filebench_log(LOG_DUMP, "<dimval>Operations/sec</dimval>");
7335184Sek110237 filebench_log(LOG_DUMP, "<dimval>MB/sec</dimval>");
7345184Sek110237 filebench_log(LOG_DUMP, "<dimval>Latency (ms per operation)</dimval>");
7355184Sek110237 filebench_log(LOG_DUMP, "<dimval>CPU (us per operation)</dimval>");
7365184Sek110237 filebench_log(LOG_DUMP, "</dim>");
7375184Sek110237
7385184Sek110237 filebench_log(LOG_DUMP, "<dim>");
7396391Saw148015 flowop = filebench_shm->shm_flowoplist;
7405184Sek110237 while (flowop) {
7415184Sek110237 if (flowop->fo_instance != FLOW_MASTER) {
7425184Sek110237 flowop = flowop->fo_next;
7435184Sek110237 continue;
7445184Sek110237 }
7455184Sek110237 filebench_log(LOG_DUMP, "<dimval>%s</dimval>", flowop->fo_name);
7465184Sek110237 flowop = flowop->fo_next;
7475184Sek110237 }
7485184Sek110237 filebench_log(LOG_DUMP, "</dim>");
7495184Sek110237 filebench_log(LOG_DUMP, "</dim_list>");
7505184Sek110237 filebench_log(LOG_DUMP, "</stat_group>");
7515184Sek110237
7525184Sek110237 filebench_log(LOG_DUMP, "<stat_group name=\"IO Summary\">");
7535184Sek110237 filebench_log(LOG_DUMP, "<cell_list>");
7545184Sek110237 filebench_log(LOG_DUMP, "<cell>%0d</cell>",
7555184Sek110237 iostat->fs_count + aiostat->fs_count);
7565184Sek110237 filebench_log(LOG_DUMP, "<cell>%0.1lf</cell>",
7575184Sek110237 (iostat->fs_count + aiostat->fs_count) /
7585184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS));
7595184Sek110237 filebench_log(LOG_DUMP, "<cell>%0.0lf</cell>",
7605184Sek110237 (iostat->fs_rcount + aiostat->fs_rcount) /
7615184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS));
7625184Sek110237 filebench_log(LOG_DUMP, "<cell>%0.0lf</cell>",
7635184Sek110237 (iostat->fs_wcount + aiostat->fs_wcount) /
7645184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS));
7655184Sek110237 filebench_log(LOG_DUMP, "<cell>%0.1lf</cell>",
7665184Sek110237 ((iostat->fs_bytes + aiostat->fs_bytes) / (1024 * 1024)) /
7675184Sek110237 ((globalstats->fs_etime - globalstats->fs_stime) / FSECS));
7685184Sek110237 filebench_log(LOG_DUMP, "<cell>%0.0f</cell>",
7695184Sek110237 (iostat->fs_rcount + iostat->fs_wcount + aiostat->fs_rcount +
7705184Sek110237 aiostat->fs_wcount) ? (iostat->fs_syscpu / 1000.0) /
7715184Sek110237 (iostat->fs_rcount + iostat->fs_wcount + aiostat->fs_rcount +
7725184Sek110237 aiostat->fs_wcount) : 0);
7735184Sek110237 filebench_log(LOG_DUMP, "</cell_list>");
7745184Sek110237
7755184Sek110237 filebench_log(LOG_DUMP, "<dim_list>");
7765184Sek110237 filebench_log(LOG_DUMP, "<dim>");
7775184Sek110237 filebench_log(LOG_DUMP, "<dimval>Operations</dimval>");
7785184Sek110237 filebench_log(LOG_DUMP, "<dimval>Operations/sec</dimval>");
7795184Sek110237 filebench_log(LOG_DUMP, "<dimval>Reads</dimval>");
7805184Sek110237 filebench_log(LOG_DUMP, "<dimval>Writes</dimval>");
7815184Sek110237 filebench_log(LOG_DUMP, "<dimval>MB/sec</dimval>");
7825184Sek110237 filebench_log(LOG_DUMP, "<dimval>CPU (us per operation)</dimval>");
7835184Sek110237 filebench_log(LOG_DUMP, "</dim>");
7845184Sek110237
7855184Sek110237 filebench_log(LOG_DUMP, "<dim>");
7865184Sek110237 filebench_log(LOG_DUMP, "<dimval>IO Summary</dimval>");
7875184Sek110237 filebench_log(LOG_DUMP, "</dim>");
7885184Sek110237 filebench_log(LOG_DUMP, "</dim_list>");
7895184Sek110237 filebench_log(LOG_DUMP, "</stat_group>");
7905184Sek110237 filebench_log(LOG_DUMP, "</stat_doc>");
7915184Sek110237 }
7925184Sek110237
7935184Sek110237 /*
7947736SAndrew.W.Wilson@sun.com * same as stats_dump, but in computer friendly format
7957736SAndrew.W.Wilson@sun.com */
7967736SAndrew.W.Wilson@sun.com void
stats_multidump(char * filename)7977736SAndrew.W.Wilson@sun.com stats_multidump(char *filename)
7987736SAndrew.W.Wilson@sun.com {
7997736SAndrew.W.Wilson@sun.com flowstat_t *iostat = &globalstats[FLOW_TYPE_IO];
8007736SAndrew.W.Wilson@sun.com flowstat_t *aiostat = &globalstats[FLOW_TYPE_AIO];
8017736SAndrew.W.Wilson@sun.com flowop_t *flowop;
8027736SAndrew.W.Wilson@sun.com
8037736SAndrew.W.Wilson@sun.com /* don't dump stats if run ended in error */
8047736SAndrew.W.Wilson@sun.com if (filebench_shm->shm_f_abort == FILEBENCH_ABORT_ERROR)
8057736SAndrew.W.Wilson@sun.com return;
8067736SAndrew.W.Wilson@sun.com
8077736SAndrew.W.Wilson@sun.com (void) strcpy(filebench_shm->shm_dump_filename, filename);
8087736SAndrew.W.Wilson@sun.com
8097736SAndrew.W.Wilson@sun.com filebench_log(LOG_INFO, "in statsmultidump %s", filename);
8107736SAndrew.W.Wilson@sun.com
8117736SAndrew.W.Wilson@sun.com if (filebench_shm->shm_dump_fd > 0) {
8127736SAndrew.W.Wilson@sun.com (void) close(filebench_shm->shm_dump_fd);
8137736SAndrew.W.Wilson@sun.com filebench_shm->shm_dump_fd = -1;
8147736SAndrew.W.Wilson@sun.com }
8157736SAndrew.W.Wilson@sun.com
8167736SAndrew.W.Wilson@sun.com filebench_log(LOG_DUMP, "Flowop totals:");
8177736SAndrew.W.Wilson@sun.com
8187736SAndrew.W.Wilson@sun.com flowop = filebench_shm->shm_flowoplist;
8197736SAndrew.W.Wilson@sun.com while (flowop) {
8207736SAndrew.W.Wilson@sun.com
8217736SAndrew.W.Wilson@sun.com if (flowop->fo_instance != FLOW_MASTER) {
8227736SAndrew.W.Wilson@sun.com flowop = flowop->fo_next;
8237736SAndrew.W.Wilson@sun.com continue;
8247736SAndrew.W.Wilson@sun.com }
8257736SAndrew.W.Wilson@sun.com
8267736SAndrew.W.Wilson@sun.com filebench_log(LOG_DUMP,
8277736SAndrew.W.Wilson@sun.com "%s\t%1.0lf\t%1.1lf\t%1.1f\t%1.0f",
8287736SAndrew.W.Wilson@sun.com flowop->fo_name,
8297736SAndrew.W.Wilson@sun.com flowop->fo_stats.fs_count /
8307736SAndrew.W.Wilson@sun.com ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
8317736SAndrew.W.Wilson@sun.com (flowop->fo_stats.fs_bytes / (1024 * 1024)) /
8327736SAndrew.W.Wilson@sun.com ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
8337736SAndrew.W.Wilson@sun.com flowop->fo_stats.fs_count ?
8347736SAndrew.W.Wilson@sun.com flowop->fo_stats.fs_mstate[FLOW_MSTATE_LAT] /
8357736SAndrew.W.Wilson@sun.com (flowop->fo_stats.fs_count * 1000000.0) : 0,
8367736SAndrew.W.Wilson@sun.com flowop->fo_stats.fs_count ?
8377736SAndrew.W.Wilson@sun.com flowop->fo_stats.fs_mstate[FLOW_MSTATE_CPU] /
8387736SAndrew.W.Wilson@sun.com (flowop->fo_stats.fs_count * 1000.0) : 0);
8397736SAndrew.W.Wilson@sun.com
8407736SAndrew.W.Wilson@sun.com flowop = flowop->fo_next;
8417736SAndrew.W.Wilson@sun.com }
8427736SAndrew.W.Wilson@sun.com
8437736SAndrew.W.Wilson@sun.com filebench_log(LOG_DUMP, "");
8447736SAndrew.W.Wilson@sun.com filebench_log(LOG_DUMP,
8457736SAndrew.W.Wilson@sun.com "IO Summary:\n%d\t%1.1lf\t%1.0lf\t%1.0lf\t%1.1lf\t%1.0f\t%1.1f\n",
8467736SAndrew.W.Wilson@sun.com
8477736SAndrew.W.Wilson@sun.com iostat->fs_count + aiostat->fs_count,
8487736SAndrew.W.Wilson@sun.com
8497736SAndrew.W.Wilson@sun.com (iostat->fs_count + aiostat->fs_count) /
8507736SAndrew.W.Wilson@sun.com ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
8517736SAndrew.W.Wilson@sun.com
8527736SAndrew.W.Wilson@sun.com (iostat->fs_rcount + aiostat->fs_rcount) /
8537736SAndrew.W.Wilson@sun.com ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
8547736SAndrew.W.Wilson@sun.com
8557736SAndrew.W.Wilson@sun.com (iostat->fs_wcount + aiostat->fs_wcount) /
8567736SAndrew.W.Wilson@sun.com ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
8577736SAndrew.W.Wilson@sun.com
8587736SAndrew.W.Wilson@sun.com ((iostat->fs_bytes + aiostat->fs_bytes) / (1024 * 1024)) /
8597736SAndrew.W.Wilson@sun.com ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
8607736SAndrew.W.Wilson@sun.com
8617736SAndrew.W.Wilson@sun.com (iostat->fs_rcount + iostat->fs_wcount +
8627736SAndrew.W.Wilson@sun.com aiostat->fs_rcount + aiostat->fs_wcount) ?
8637736SAndrew.W.Wilson@sun.com (iostat->fs_syscpu / 1000.0) /
8647736SAndrew.W.Wilson@sun.com (iostat->fs_rcount + iostat->fs_wcount +
8657736SAndrew.W.Wilson@sun.com aiostat->fs_rcount + aiostat->fs_wcount) : 0,
8667736SAndrew.W.Wilson@sun.com
8677736SAndrew.W.Wilson@sun.com (iostat->fs_rcount + iostat->fs_wcount) ?
8687736SAndrew.W.Wilson@sun.com iostat->fs_mstate[FLOW_MSTATE_LAT] /
8697736SAndrew.W.Wilson@sun.com ((iostat->fs_rcount + iostat->fs_wcount) * 1000000.0) : 0);
8707736SAndrew.W.Wilson@sun.com }
8717736SAndrew.W.Wilson@sun.com
8727736SAndrew.W.Wilson@sun.com /*
8735184Sek110237 * Clears all the statistics variables (fo_stats) for every defined flowop.
8745184Sek110237 * It also creates a global flowstat table if one doesn't already exist and
8755184Sek110237 * clears it.
8765184Sek110237 */
8775184Sek110237 void
stats_clear(void)8785184Sek110237 stats_clear(void)
8795184Sek110237 {
8805184Sek110237 flowop_t *flowop;
8815184Sek110237
8825184Sek110237 #ifdef HAVE_LIBKSTAT
8835184Sek110237 stats_cputime = kstats_read_cpu();
8845184Sek110237 #else
8855184Sek110237 stats_cputime = 0;
8865184Sek110237 #endif /* HAVE_LIBKSTAT */
8875184Sek110237
8885184Sek110237 if (globalstats == NULL)
8895184Sek110237 globalstats = malloc(FLOW_TYPES * sizeof (flowstat_t));
8905184Sek110237
8915184Sek110237 (void) memset(globalstats, 0, FLOW_TYPES * sizeof (flowstat_t));
8925184Sek110237
8936391Saw148015 flowop = filebench_shm->shm_flowoplist;
8945184Sek110237
8955184Sek110237 while (flowop) {
8965184Sek110237 filebench_log(LOG_DEBUG_IMPL, "Clearing stats for %s-%d",
8975184Sek110237 flowop->fo_name,
8985184Sek110237 flowop->fo_instance);
8995184Sek110237 (void) memset(&flowop->fo_stats, 0, sizeof (flowstat_t));
9005184Sek110237 flowop = flowop->fo_next;
9015184Sek110237 }
9025184Sek110237
9035184Sek110237 (void) memset(globalstats, 0, sizeof (flowstat_t));
9045184Sek110237 globalstats->fs_stime = gethrtime();
9055184Sek110237 }
906