xref: /onnv-gate/usr/src/cmd/filebench/common/stats.c (revision 7736:affefef63864)
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 /*
226084Saw148015  * Copyright 2008 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;
615184Sek110237 
625184Sek110237 /*
635184Sek110237  * Uses the kstat library or, if it is not available, the /proc/stat file
645184Sek110237  * to obtain cpu statistics. Collects statistics for each cpu, initializes
655184Sek110237  * a local pointer to the sysinfo kstat, and returns the sum of user and
665184Sek110237  * kernel time for all the cpus.
675184Sek110237  */
686212Saw148015 static fbint_t
695184Sek110237 kstats_read_cpu(void)
705184Sek110237 {
715184Sek110237 	int ncpus;
725184Sek110237 	kstat_t	**cpu_stat_list = NULL;
735184Sek110237 	ulong_t cputime_states[CPU_STATES];
745184Sek110237 	hrtime_t cputime;
755184Sek110237 	int i;
765184Sek110237 
775184Sek110237 	kstat_t *ksp;
785184Sek110237 
795184Sek110237 	if (kstatp == NULL) {
805184Sek110237 		if ((kstatp = kstat_open()) == (kstat_ctl_t *)NULL) {
815184Sek110237 			filebench_log(LOG_ERROR, "Cannot read kstats");
825184Sek110237 			return (-1);
835184Sek110237 		}
845184Sek110237 	}
855184Sek110237 
865184Sek110237 	/*
875184Sek110237 	 * Per-CPU statistics
885184Sek110237 	 */
895184Sek110237 
905184Sek110237 	ncpus = 0;
915184Sek110237 	for (ksp = kstatp->kc_chain; ksp; ksp = ksp->ks_next)
925184Sek110237 		if (strncmp(ksp->ks_name, "cpu_stat", 8) == 0)
935184Sek110237 			ncpus++;
945184Sek110237 
955184Sek110237 	if ((cpu_stat_list =
965184Sek110237 	    (kstat_t **)malloc(ncpus * sizeof (kstat_t *))) == NULL) {
975184Sek110237 		filebench_log(LOG_ERROR, "malloc failed");
985184Sek110237 		return (-1);
995184Sek110237 	}
1005184Sek110237 
1015184Sek110237 	ncpus = 0;
1025184Sek110237 	for (ksp = kstatp->kc_chain; ksp; ksp = ksp->ks_next)
1035184Sek110237 		if (strncmp(ksp->ks_name, "cpu_stat", 8) == 0 &&
1045184Sek110237 		    kstat_read(kstatp, ksp, NULL) != -1)
1055184Sek110237 			cpu_stat_list[ncpus++] = ksp;
1065184Sek110237 
1075184Sek110237 	if (ncpus == 0) {
1085184Sek110237 		filebench_log(LOG_ERROR,
1095184Sek110237 		    "kstats can't find any cpu statistics");
1105184Sek110237 		return (0);
1115184Sek110237 	}
1125184Sek110237 
1135184Sek110237 	if (sysinfo_ksp == NULL)
1145184Sek110237 		sysinfo_ksp = kstat_lookup(kstatp, "unix", 0, "sysinfo");
1155184Sek110237 
1165184Sek110237 	/* Sum across all CPUs */
1175184Sek110237 	(void) memset(&cputime_states, 0, sizeof (cputime_states));
1185184Sek110237 	for (i = 0; i < ncpus; i++) {
1195184Sek110237 		cpu_stat_t cpu_stats;
1205184Sek110237 		int j;
1215184Sek110237 
1225184Sek110237 		(void) kstat_read(kstatp, cpu_stat_list[i],
1235184Sek110237 		    (void *) &cpu_stats);
1245184Sek110237 		for (j = 0; j < CPU_STATES; j++)
1255184Sek110237 			cputime_states[j] += cpu_stats.cpu_sysinfo.cpu[j];
1265184Sek110237 	}
1275184Sek110237 
1285184Sek110237 	cputime = cputime_states[CPU_KERNEL] + cputime_states[CPU_USER];
1295184Sek110237 
1305184Sek110237 	return (10000000LL * cputime);
1315184Sek110237 }
1325184Sek110237 #else /* HAVE_LIBKSTAT */
1335184Sek110237 #ifdef HAVE_PROC_STAT
1345184Sek110237 static FILE *statfd = 0;
1356212Saw148015 fbint_t
1365184Sek110237 kstats_read_cpu(void)
1375184Sek110237 {
1385184Sek110237 	/*
1395184Sek110237 	 * Linux provides system wide statistics in /proc/stat
1405184Sek110237 	 * The entry for cpu is
1415184Sek110237 	 * cpu  1636 67 1392 208671 5407 20 12
1425184Sek110237 	 * cpu0 626 8 997 104476 2499 7 7
1435184Sek110237 	 * cpu1 1010 58 395 104195 2907 13 5
1445184Sek110237 	 *
1455184Sek110237 	 * The number of jiffies (1/100ths of  a  second)  that  the
1465184Sek110237 	 * system  spent  in  user mode, user mode with low priority
1475184Sek110237 	 * (nice), system mode, and  the  idle  task,  respectively.
1485184Sek110237 	 */
1495184Sek110237 	unsigned int user, nice, system;
1505184Sek110237 	char cpu[128]; /* placeholder to read "cpu" */
1515184Sek110237 	if (statfd == 0) {
1525184Sek110237 		statfd = fopen("/proc/stat", "r");
1535184Sek110237 		if (statfd < 0) {
1545184Sek110237 			filebench_log(LOG_ERROR, "Cannot open /proc/stat");
1555184Sek110237 			return (-1);
1565184Sek110237 		}
1575184Sek110237 	}
1585184Sek110237 	if (fscanf(statfd, "%s %u %u %u", cpu, &user, &nice, &system) < 0) {
1595184Sek110237 		filebench_log(LOG_ERROR, "Cannot read /proc/stat");
1605184Sek110237 		return (-1);
1615184Sek110237 	}
1625184Sek110237 	/* convert jiffies to nanosecs */
1635184Sek110237 	return ((user+nice+system)*1000000);
1645184Sek110237 }
1655184Sek110237 
1665184Sek110237 #else /* HAVE_PROC_STAT */
1676212Saw148015 fbint_t
1685184Sek110237 kstats_read_cpu(void)
1695184Sek110237 {
1705184Sek110237 	return (0);
1715184Sek110237 }
1725184Sek110237 #endif
1735184Sek110237 #endif /* HAVE_LIBKSTAT */
1745184Sek110237 
1755184Sek110237 /*
1765184Sek110237  * Returns the net cpu time used since the beginning of the run.
1775184Sek110237  * Just calls kstat_read_cpu() and subtracts stats_cputime which
1785184Sek110237  * is set at the beginning of the filebench run.
1795184Sek110237  */
1805184Sek110237 static hrtime_t
1815184Sek110237 kstats_read_cpu_relative(void)
1825184Sek110237 {
1835184Sek110237 	hrtime_t cputime;
1845184Sek110237 
1855184Sek110237 	cputime = kstats_read_cpu();
1865184Sek110237 	return (cputime - stats_cputime);
1875184Sek110237 }
1885184Sek110237 
1895184Sek110237 /*
1905184Sek110237  * IO Overhead CPU is the amount of CPU that is incurred running
1915184Sek110237  * the benchmark infrastructure.
1925184Sek110237  *
1935184Sek110237  * It is computed as the sum of micro-state cpu time for each
1945184Sek110237  * thread around the op being tested.
1955184Sek110237  *
1965184Sek110237  * Overhead time is computed for each flow.
1975184Sek110237  *
1985184Sek110237  * System overhead is computed as the overhead for I/O flows
1995184Sek110237  * plus all other time running non-io related flowops
2005184Sek110237  *
2015184Sek110237  */
2025184Sek110237 
2035184Sek110237 /*
2045184Sek110237  * Computes and returns the overhead CPU time attibutable to
2055184Sek110237  * IO type flowops.
2065184Sek110237  */
2075184Sek110237 static hrtime_t
2085184Sek110237 io_stats_ohead(void)
2095184Sek110237 {
2105184Sek110237 	flowstat_t *iostat = &globalstats[FLOW_TYPE_IO];
2115184Sek110237 	flowstat_t *aiostat = &globalstats[FLOW_TYPE_AIO];
2125184Sek110237 	flowstat_t *glstat = &globalstats[FLOW_TYPE_GLOBAL];
2135184Sek110237 
2145184Sek110237 	filebench_log(LOG_DEBUG_NEVER,
2156286Saw148015 	    "Computing overhead as %llu + %llu - %llu - %llu",
2166286Saw148015 	    (u_longlong_t)glstat->fs_mstate[FLOW_MSTATE_OHEAD],
2176286Saw148015 	    (u_longlong_t)glstat->fs_mstate[FLOW_MSTATE_CPU],
2186286Saw148015 	    (u_longlong_t)iostat->fs_mstate[FLOW_MSTATE_CPU],
2196286Saw148015 	    (u_longlong_t)aiostat->fs_mstate[FLOW_MSTATE_CPU]);
2205184Sek110237 
2215184Sek110237 	return ((glstat->fs_mstate[FLOW_MSTATE_OHEAD] +
2225184Sek110237 	    glstat->fs_mstate[FLOW_MSTATE_CPU] -
2235184Sek110237 	    iostat->fs_mstate[FLOW_MSTATE_CPU] -
2245184Sek110237 	    aiostat->fs_mstate[FLOW_MSTATE_CPU]));
2255184Sek110237 }
2265184Sek110237 
2275184Sek110237 /*
2285184Sek110237  * Returns the total overhead CPU time.
2295184Sek110237  */
2305184Sek110237 static hrtime_t
2315184Sek110237 gl_stats_ohead(void)
2325184Sek110237 {
2335184Sek110237 	flowstat_t *glstat = &globalstats[FLOW_TYPE_GLOBAL];
2345184Sek110237 
2355184Sek110237 	return (glstat->fs_mstate[FLOW_MSTATE_OHEAD]);
2365184Sek110237 }
2375184Sek110237 
2385184Sek110237 /*
2396212Saw148015  * Places the value represented by "name" into the var_val.integer field of the
2405184Sek110237  * supplied var_t. Compares the supplied "name" with a set of predefined
2415184Sek110237  * names and calculates the value from the appropriate globalstats field(s).
2425184Sek110237  */
2435184Sek110237 var_t *
2445184Sek110237 stats_findvar(var_t *var, char *name)
2455184Sek110237 {
2465184Sek110237 	flowstat_t *iostat = &globalstats[FLOW_TYPE_IO];
2475184Sek110237 	flowstat_t *aiostat = &globalstats[FLOW_TYPE_AIO];
2485184Sek110237 	flowstat_t *glstat = &globalstats[FLOW_TYPE_GLOBAL];
2495184Sek110237 
2505184Sek110237 	filebench_log(LOG_DEBUG_IMPL, "reading stats %s", name);
2515184Sek110237 
2525184Sek110237 	if (globalstats == NULL)
2535184Sek110237 		globalstats = malloc(FLOW_TYPES * sizeof (flowstat_t));
2545184Sek110237 
2555184Sek110237 	if (strcmp(name, "iocount") == 0) {
2566212Saw148015 		fbint_t stat;
2576212Saw148015 
2586212Saw148015 		stat = iostat->fs_count + aiostat->fs_count;
2596212Saw148015 		VAR_SET_INT(var, stat);
2606286Saw148015 		filebench_log(LOG_DEBUG_IMPL, "reading stats %s = %llu",
2616286Saw148015 		    name, (u_longlong_t)stat);
2625184Sek110237 		return (var);
2635184Sek110237 	}
2645184Sek110237 
2655184Sek110237 	if (strcmp(name, "iorate") == 0) {
2666212Saw148015 		fbint_t stat;
2676212Saw148015 
2685184Sek110237 		/* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
2696212Saw148015 		stat = (iostat->fs_count + aiostat->fs_count) /
2705184Sek110237 		    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS);
2716212Saw148015 		VAR_SET_INT(var, stat);
2725184Sek110237 		return (var);
2735184Sek110237 	}
2745184Sek110237 
2755184Sek110237 
2765184Sek110237 	if (strcmp(name, "ioreadrate") == 0) {
2776212Saw148015 		fbint_t stat;
2786212Saw148015 
2795184Sek110237 		/* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
2806212Saw148015 		stat = (iostat->fs_rcount + aiostat->fs_rcount) /
2815184Sek110237 		    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS);
2826212Saw148015 		VAR_SET_INT(var, stat);
2835184Sek110237 		return (var);
2845184Sek110237 	}
2855184Sek110237 
2865184Sek110237 
2875184Sek110237 	if (strcmp(name, "iowriterate") == 0) {
2886212Saw148015 		fbint_t stat;
2896212Saw148015 
2905184Sek110237 		/* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
2916212Saw148015 		stat = (iostat->fs_wcount + aiostat->fs_wcount) /
2925184Sek110237 		    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS);
2936212Saw148015 		VAR_SET_INT(var, stat);
2945184Sek110237 		return (var);
2955184Sek110237 	}
2965184Sek110237 
2975184Sek110237 
2985184Sek110237 	if (strcmp(name, "iobandwidth") == 0) {
2996212Saw148015 		fbint_t stat;
3006212Saw148015 
3015184Sek110237 		/* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
3026212Saw148015 		stat =
3035184Sek110237 		    ((iostat->fs_bytes + aiostat->fs_bytes) / (1024 * 1024)) /
3045184Sek110237 		    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS);
3056212Saw148015 		VAR_SET_INT(var, stat);
3065184Sek110237 		return (var);
3075184Sek110237 	}
3085184Sek110237 
3095184Sek110237 	if (strcmp(name, "iolatency") == 0) {
3106212Saw148015 		fbint_t stat;
3116212Saw148015 
3126212Saw148015 		stat = iostat->fs_count ? iostat->fs_mstate[FLOW_MSTATE_LAT] /
3135184Sek110237 		    (iostat->fs_count * 1000UL) : 0;
3146212Saw148015 		VAR_SET_INT(var, stat);
3155184Sek110237 		return (var);
3165184Sek110237 	}
3175184Sek110237 
3185184Sek110237 	if (strcmp(name, "iocpu") == 0) {
3196212Saw148015 		fbint_t stat;
3206212Saw148015 
3216212Saw148015 		stat = (iostat->fs_count + aiostat->fs_count) ?
3225184Sek110237 		    (iostat->fs_mstate[FLOW_MSTATE_CPU] +
3235184Sek110237 		    aiostat->fs_mstate[FLOW_MSTATE_CPU]) / ((iostat->fs_count +
3245184Sek110237 		    aiostat->fs_count) * 1000UL) : 0;
3256212Saw148015 		VAR_SET_INT(var, stat);
3265184Sek110237 		return (var);
3275184Sek110237 	}
3285184Sek110237 
3295184Sek110237 
3305184Sek110237 	if (strcmp(name, "oheadcpu") == 0) {
3316212Saw148015 		fbint_t stat;
3326212Saw148015 
3336212Saw148015 		stat = (iostat->fs_count + aiostat->fs_count) ?
3345184Sek110237 		    io_stats_ohead() / ((iostat->fs_count +
3355184Sek110237 		    aiostat->fs_count) * 1000UL) : 0;
3366212Saw148015 		VAR_SET_INT(var, stat);
3375184Sek110237 		return (var);
3385184Sek110237 	}
3395184Sek110237 
3405184Sek110237 	if (strcmp(name, "iowait") == 0) {
3416212Saw148015 		fbint_t stat;
3426212Saw148015 
3436212Saw148015 		stat = iostat->fs_count ?
3445184Sek110237 		    iostat->fs_mstate[FLOW_MSTATE_WAIT] /
3455184Sek110237 		    (iostat->fs_count * 1000UL) : 0;
3466212Saw148015 		VAR_SET_INT(var, stat);
3475184Sek110237 		return (var);
3485184Sek110237 	}
3495184Sek110237 
3505184Sek110237 	if (strcmp(name, "syscpu") == 0) {
3516212Saw148015 		fbint_t stat;
3526212Saw148015 
3535184Sek110237 		/* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
3546212Saw148015 		stat = glstat->fs_syscpu / 1000.0;
3556212Saw148015 		VAR_SET_INT(var, stat);
3565184Sek110237 		return (var);
3575184Sek110237 	}
3585184Sek110237 
3595184Sek110237 	if (strcmp(name, "iocpusys") == 0) {
3606212Saw148015 		fbint_t stat;
3616212Saw148015 
3626212Saw148015 		stat = (iostat->fs_count + aiostat->fs_count) ?
3635184Sek110237 		    iostat->fs_syscpu / ((iostat->fs_count +
3645184Sek110237 		    aiostat->fs_count) * 1000UL) : 0;
3655184Sek110237 
3666212Saw148015 		VAR_SET_INT(var, stat);
3675184Sek110237 		return (var);
3685184Sek110237 	}
3695184Sek110237 
3705184Sek110237 	filebench_log(LOG_DEBUG_IMPL,
3715184Sek110237 	    "error reading stats %s", name);
3725184Sek110237 
3735184Sek110237 	return (NULL);
3745184Sek110237 }
3755184Sek110237 
3765184Sek110237 /*
3775184Sek110237  * Initializes the static variable "stats_cputime" with the
3785184Sek110237  * current cpu time, for use by kstats_read_cpu_relative.
3795184Sek110237  */
3805184Sek110237 void
3815184Sek110237 stats_init(void)
3825184Sek110237 {
3835184Sek110237 #if defined(HAVE_LIBKSTAT) || defined(LINUX_PORT)
3845184Sek110237 	stats_cputime = kstats_read_cpu();
3855184Sek110237 #else
3865184Sek110237 	stats_cputime = 0;
3875184Sek110237 #endif /* HAVE_LIBKSTAT */
3885184Sek110237 }
3895184Sek110237 
3905184Sek110237 /*
3915184Sek110237  * Add a flowstat b to a, leave sum in a.
3925184Sek110237  */
3935184Sek110237 static void
3945184Sek110237 stats_add(flowstat_t *a, flowstat_t *b)
3955184Sek110237 {
3965184Sek110237 	int i;
3975184Sek110237 
3985184Sek110237 	a->fs_count += b->fs_count;
3995184Sek110237 	a->fs_rcount += b->fs_rcount;
4005184Sek110237 	a->fs_wcount += b->fs_wcount;
4015184Sek110237 	a->fs_bytes += b->fs_bytes;
4025184Sek110237 	a->fs_rbytes += b->fs_rbytes;
4035184Sek110237 	a->fs_wbytes += b->fs_wbytes;
4045184Sek110237 
4055184Sek110237 	for (i = 0; i < FLOW_MSTATES; i++)
4065184Sek110237 		a->fs_mstate[i] += b->fs_mstate[i];
4075184Sek110237 }
4085184Sek110237 
4095184Sek110237 /*
4105184Sek110237  * Takes a "snapshot" of the global statistics. Actually, it calculates
4115184Sek110237  * them from the local statistics maintained by each flowop.
4125184Sek110237  * First the routine pauses filebench, then rolls the statistics for
4135184Sek110237  * each flowop into its associated FLOW_MASTER flowop.
4145184Sek110237  * Next all the FLOW_MASTER flowops' statistics are written
4155184Sek110237  * to the log file followed by the global totals. Then filebench
4165184Sek110237  * operation is allowed to resume.
4175184Sek110237  */
4185184Sek110237 void
4195184Sek110237 stats_snap(void)
4205184Sek110237 {
4215184Sek110237 	flowstat_t *iostat = &globalstats[FLOW_TYPE_IO];
4225184Sek110237 	flowstat_t *aiostat = &globalstats[FLOW_TYPE_AIO];
4235184Sek110237 	flowstat_t *glstat = &globalstats[FLOW_TYPE_GLOBAL];
4245184Sek110237 	hrtime_t cputime;
4255184Sek110237 	flowop_t *flowop;
4265184Sek110237 	char *str;
4275184Sek110237 
4285184Sek110237 	if (globalstats == NULL) {
4295184Sek110237 		filebench_log(LOG_ERROR,
4305184Sek110237 		    "'stats snap' called before 'stats clear'");
4315184Sek110237 		return;
4325184Sek110237 	}
4335184Sek110237 
4346084Saw148015 	/* don't print out if run ended in error */
4356391Saw148015 	if (filebench_shm->shm_f_abort == FILEBENCH_ABORT_ERROR) {
4366084Saw148015 		filebench_log(LOG_ERROR,
4376084Saw148015 		    "NO VALID RESULTS! FileBench run terminated prematurely");
4386084Saw148015 		return;
4396084Saw148015 	}
4406084Saw148015 
4415184Sek110237 	globalstats->fs_etime = gethrtime();
4425184Sek110237 
4435184Sek110237 	filebench_log(LOG_DEBUG_SCRIPT, "Stats period = %ds",
4445184Sek110237 	    (globalstats->fs_etime - globalstats->fs_stime) / 1000000000);
4455184Sek110237 
4465184Sek110237 	/* Freeze statistics during update */
4476391Saw148015 	filebench_shm->shm_bequiet = 1;
4485184Sek110237 
4496391Saw148015 	flowop = filebench_shm->shm_flowoplist;
4505184Sek110237 	while (flowop) {
4515184Sek110237 		flowop_t *flowop_master;
4525184Sek110237 
4536212Saw148015 		if (flowop->fo_instance <= FLOW_DEFINITION) {
4545184Sek110237 			flowop = flowop->fo_next;
4555184Sek110237 			continue;
4565184Sek110237 		}
4575184Sek110237 
4586212Saw148015 		flowop_master = flowop_find_one(flowop->fo_name, FLOW_MASTER);
4595184Sek110237 
4605184Sek110237 		/* Roll up per-flowop into global stats */
4615184Sek110237 		stats_add(&globalstats[flowop->fo_type],
4625184Sek110237 		    &flowop->fo_stats);
4635184Sek110237 		stats_add(&globalstats[FLOW_TYPE_GLOBAL],
4645184Sek110237 		    &flowop->fo_stats);
4655184Sek110237 
4665184Sek110237 		if (flowop_master && IS_FLOW_ACTIVE(flowop)) {
4675184Sek110237 			flowop_master->fo_stats.fs_active++;
4685184Sek110237 		}
4695184Sek110237 
4705184Sek110237 		if (flowop_master) {
4715184Sek110237 			/* Roll up per-flow stats into master */
4725184Sek110237 			flowop_master->fo_stats.fs_children++;
4735184Sek110237 			stats_add(&flowop_master->fo_stats, &flowop->fo_stats);
4745184Sek110237 		} else {
4755184Sek110237 			filebench_log(LOG_DEBUG_NEVER,
4765184Sek110237 			    "flowop_stats could not find %s",
4775184Sek110237 			    flowop->fo_name);
4785184Sek110237 		}
4795184Sek110237 
4805184Sek110237 		filebench_log(LOG_DEBUG_SCRIPT,
4815184Sek110237 		    "flowop %-20s-%4d  - %5d ops, %5.1lf, ops/s %5.1lfmb/s "
4825184Sek110237 		    "%8.3fms/op",
4835184Sek110237 		    flowop->fo_name,
4845184Sek110237 		    flowop->fo_instance,
4855184Sek110237 		    flowop->fo_stats.fs_count,
4865184Sek110237 		    flowop->fo_stats.fs_count /
4875184Sek110237 		    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
4885184Sek110237 		    (flowop->fo_stats.fs_bytes / (1024 * 1024)) /
4895184Sek110237 		    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
4905184Sek110237 		    flowop->fo_stats.fs_count ?
4915184Sek110237 		    flowop->fo_stats.fs_mstate[FLOW_MSTATE_LAT] /
4925184Sek110237 		    (flowop->fo_stats.fs_count * 1000000.0) : 0);
4935184Sek110237 
4945184Sek110237 		flowop = flowop->fo_next;
4955184Sek110237 
4965184Sek110237 	}
4975184Sek110237 
4985184Sek110237 #if defined(HAVE_LIBKSTAT) || defined(LINUX_PORT)
4995184Sek110237 	cputime = kstats_read_cpu_relative();
5005184Sek110237 #endif /* HAVE_LIBKSTAT */
5015184Sek110237 
5025184Sek110237 	filebench_log(LOG_DEBUG_IMPL,
5036286Saw148015 	    "cputime = %llu, ohead = %llu",
5046286Saw148015 	    (u_longlong_t)(cputime / 1000000000),
5056286Saw148015 	    (u_longlong_t)(io_stats_ohead() / 1000000000));
5065184Sek110237 	iostat->fs_syscpu =
5075184Sek110237 	    (cputime > io_stats_ohead()) ?
5085184Sek110237 	    (cputime - io_stats_ohead()) : 0;
5095184Sek110237 	glstat->fs_syscpu =
5105184Sek110237 	    (cputime > gl_stats_ohead()) ?
5115184Sek110237 	    (cputime - gl_stats_ohead()) : 0;
5125184Sek110237 
5135184Sek110237 
5146391Saw148015 	flowop = filebench_shm->shm_flowoplist;
5155184Sek110237 	str = malloc(1048576);
5166613Sek110237 	*str = '\0';
5175184Sek110237 	(void) strcpy(str, "Per-Operation Breakdown\n");
5185184Sek110237 	while (flowop) {
5195184Sek110237 		char line[1024];
5205184Sek110237 
5215184Sek110237 		if (flowop->fo_instance != FLOW_MASTER) {
5225184Sek110237 			flowop = flowop->fo_next;
5235184Sek110237 			continue;
5245184Sek110237 		}
5255184Sek110237 
5265184Sek110237 		(void) snprintf(line, sizeof (line), "%-20s %8.0lfops/s "
5275184Sek110237 		    "%5.1lfmb/s %8.1fms/op %8.0fus/op-cpu\n",
5285184Sek110237 		    flowop->fo_name,
5295184Sek110237 		    flowop->fo_stats.fs_count /
5305184Sek110237 		    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
5315184Sek110237 		    (flowop->fo_stats.fs_bytes / (1024 * 1024)) /
5325184Sek110237 		    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
5335184Sek110237 		    flowop->fo_stats.fs_count ?
5345184Sek110237 		    flowop->fo_stats.fs_mstate[FLOW_MSTATE_LAT] /
5355184Sek110237 		    (flowop->fo_stats.fs_count * 1000000.0) : 0,
5365184Sek110237 		    flowop->fo_stats.fs_count ?
5375184Sek110237 		    flowop->fo_stats.fs_mstate[FLOW_MSTATE_CPU] /
5385184Sek110237 		    (flowop->fo_stats.fs_count * 1000.0) : 0);
5395184Sek110237 		(void) strcat(str, line);
5405184Sek110237 
5415184Sek110237 		flowop = flowop->fo_next;
5425184Sek110237 	}
5435184Sek110237 
5445184Sek110237 	filebench_log(LOG_INFO, "%s", str);
5455184Sek110237 	free(str);
5465184Sek110237 
5475184Sek110237 	filebench_log(LOG_INFO,
548*7736SAndrew.W.Wilson@sun.com 	    "\nIO Summary:      %5d ops, %5.1lf ops/s, (%0.0lf/%0.0lf r/w) "
5495184Sek110237 	    "%5.1lfmb/s, %6.0fus cpu/op, %5.1fms latency",
5505184Sek110237 	    iostat->fs_count + aiostat->fs_count,
5515184Sek110237 	    (iostat->fs_count + aiostat->fs_count) /
5525184Sek110237 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
5535184Sek110237 	    (iostat->fs_rcount + aiostat->fs_rcount) /
5545184Sek110237 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
5555184Sek110237 	    (iostat->fs_wcount + aiostat->fs_wcount) /
5565184Sek110237 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
5575184Sek110237 	    ((iostat->fs_bytes + aiostat->fs_bytes) / (1024 * 1024)) /
5585184Sek110237 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
5595184Sek110237 	    (iostat->fs_rcount + iostat->fs_wcount +
5605184Sek110237 	    aiostat->fs_rcount + aiostat->fs_wcount) ?
5615184Sek110237 	    (iostat->fs_syscpu / 1000.0) /
5625184Sek110237 	    (iostat->fs_rcount + iostat->fs_wcount +
5635184Sek110237 	    aiostat->fs_rcount + aiostat->fs_wcount) : 0,
5645184Sek110237 	    (iostat->fs_rcount + iostat->fs_wcount) ?
5655184Sek110237 	    iostat->fs_mstate[FLOW_MSTATE_LAT] /
5665184Sek110237 	    ((iostat->fs_rcount + iostat->fs_wcount) * 1000000.0) : 0);
5675184Sek110237 
5685184Sek110237 
5696391Saw148015 	filebench_shm->shm_bequiet = 0;
5705184Sek110237 }
5715184Sek110237 
5725184Sek110237 /*
5735184Sek110237  * Dumps the per-operation statistics and global statistics to the dump file.
5745184Sek110237  */
5755184Sek110237 void
5765184Sek110237 stats_dump(char *filename)
5775184Sek110237 {
5785184Sek110237 	flowstat_t *iostat = &globalstats[FLOW_TYPE_IO];
5795184Sek110237 	flowstat_t *aiostat = &globalstats[FLOW_TYPE_AIO];
5805184Sek110237 	flowop_t *flowop;
5815184Sek110237 
5826084Saw148015 	/* don't dump stats if run ended in error */
5836391Saw148015 	if (filebench_shm->shm_f_abort == FILEBENCH_ABORT_ERROR)
5846084Saw148015 		return;
5856084Saw148015 
5866391Saw148015 	(void) strcpy(filebench_shm->shm_dump_filename, filename);
5875184Sek110237 
5885184Sek110237 	filebench_log(LOG_INFO, "in statsdump %s", filename);
5895184Sek110237 
5906391Saw148015 	if (filebench_shm->shm_dump_fd > 0) {
5916391Saw148015 		(void) close(filebench_shm->shm_dump_fd);
5926391Saw148015 		filebench_shm->shm_dump_fd = -1;
5935184Sek110237 	}
5945184Sek110237 
5955184Sek110237 	filebench_log(LOG_DUMP, "Flowop totals:");
5965184Sek110237 
5976391Saw148015 	flowop = filebench_shm->shm_flowoplist;
5985184Sek110237 	while (flowop) {
5995184Sek110237 
6005184Sek110237 		if (flowop->fo_instance != FLOW_MASTER) {
6015184Sek110237 			flowop = flowop->fo_next;
6025184Sek110237 			continue;
6035184Sek110237 		}
6045184Sek110237 
6055184Sek110237 		filebench_log(LOG_DUMP,
6065184Sek110237 		    "%-20s %8.0lfops/s %5.1lfmb/s "
6075184Sek110237 		    "%8.1fms/op %8.0fus/op-cpu",
6085184Sek110237 		    flowop->fo_name,
6095184Sek110237 		    flowop->fo_stats.fs_count /
6105184Sek110237 		    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
6115184Sek110237 		    (flowop->fo_stats.fs_bytes / (1024 * 1024)) /
6125184Sek110237 		    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
6135184Sek110237 		    flowop->fo_stats.fs_count ?
6145184Sek110237 		    flowop->fo_stats.fs_mstate[FLOW_MSTATE_LAT] /
6155184Sek110237 		    (flowop->fo_stats.fs_count * 1000000.0) : 0,
6165184Sek110237 		    flowop->fo_stats.fs_count ?
6175184Sek110237 		    flowop->fo_stats.fs_mstate[FLOW_MSTATE_CPU] /
6185184Sek110237 		    (flowop->fo_stats.fs_count * 1000.0) : 0);
6195184Sek110237 
6205184Sek110237 		flowop = flowop->fo_next;
6215184Sek110237 	}
6225184Sek110237 
6235184Sek110237 	filebench_log(LOG_DUMP, "");
6245184Sek110237 	filebench_log(LOG_DUMP,
6255184Sek110237 	    "IO Summary:      %8d ops %8.1lf ops/s, %8.0lf/%0.0lf r/w"
6265184Sek110237 	    "%8.1lfmb/s, %8.0fuscpu/op",
6275184Sek110237 
6285184Sek110237 	    iostat->fs_count + aiostat->fs_count,
6295184Sek110237 	    (iostat->fs_count + aiostat->fs_count) /
6305184Sek110237 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
6315184Sek110237 
6325184Sek110237 	    (iostat->fs_rcount + aiostat->fs_rcount) /
6335184Sek110237 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
6345184Sek110237 
6355184Sek110237 	    (iostat->fs_wcount + aiostat->fs_wcount) /
6365184Sek110237 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
6375184Sek110237 
6385184Sek110237 	    ((iostat->fs_bytes + aiostat->fs_bytes) / (1024 * 1024)) /
6395184Sek110237 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
6405184Sek110237 
6415184Sek110237 	    (iostat->fs_rcount + iostat->fs_wcount +
6425184Sek110237 	    aiostat->fs_rcount + aiostat->fs_wcount) ?
6435184Sek110237 	    (iostat->fs_syscpu / 1000.0) /
6445184Sek110237 	    (iostat->fs_rcount + iostat->fs_wcount +
6455184Sek110237 	    aiostat->fs_rcount + aiostat->fs_wcount) : 0);
6465184Sek110237 }
6475184Sek110237 
6485184Sek110237 /*
6495184Sek110237  * Same as stats_dump, but in xml format.
6505184Sek110237  */
6515184Sek110237 void
6525184Sek110237 stats_xmldump(char *filename)
6535184Sek110237 {
6545184Sek110237 	flowstat_t *iostat = &globalstats[FLOW_TYPE_IO];
6555184Sek110237 	flowstat_t *aiostat = &globalstats[FLOW_TYPE_AIO];
6565184Sek110237 	flowop_t *flowop;
6575184Sek110237 
6586084Saw148015 	/* don't dump stats if run ended in error */
6596391Saw148015 	if (filebench_shm->shm_f_abort == FILEBENCH_ABORT_ERROR)
6606084Saw148015 		return;
6616084Saw148015 
6626391Saw148015 	(void) strcpy(filebench_shm->shm_dump_filename, filename);
6635184Sek110237 
6646391Saw148015 	if (filebench_shm->shm_dump_fd > 0) {
6656391Saw148015 		(void) close(filebench_shm->shm_dump_fd);
6666391Saw148015 		filebench_shm->shm_dump_fd = -1;
6675184Sek110237 	}
6685184Sek110237 
6695184Sek110237 	filebench_log(LOG_DUMP, "<stat_doc name=\"Filebench Workload\">");
6705184Sek110237 	filebench_log(LOG_DUMP, "<stat_group name=\"Flowop totals\">");
6715184Sek110237 	filebench_log(LOG_DUMP, "<cell_list>");
6725184Sek110237 
6736391Saw148015 	flowop = filebench_shm->shm_flowoplist;
6745184Sek110237 	while (flowop) {
6755184Sek110237 		if (flowop->fo_instance != FLOW_MASTER) {
6765184Sek110237 			flowop = flowop->fo_next;
6775184Sek110237 			continue;
6785184Sek110237 		}
6795184Sek110237 
6805184Sek110237 		filebench_log(LOG_DUMP, "<cell>%0.0lf</cell>",
6815184Sek110237 		    flowop->fo_stats.fs_count /
6825184Sek110237 		    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS));
6835184Sek110237 		filebench_log(LOG_DUMP, "<cell>%0.1lf</cell>",
6845184Sek110237 		    (flowop->fo_stats.fs_bytes / (1024 * 1024)) /
6855184Sek110237 		    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS));
6865184Sek110237 		filebench_log(LOG_DUMP, "<cell>%0.1lf</cell>",
6875184Sek110237 		    flowop->fo_stats.fs_count ?
6885184Sek110237 		    flowop->fo_stats.fs_mstate[FLOW_MSTATE_LAT] /
6895184Sek110237 		    (flowop->fo_stats.fs_count * 1000000.0) : 0);
6905184Sek110237 		filebench_log(LOG_DUMP, "<cell>%0.0lf</cell>",
6915184Sek110237 		    flowop->fo_stats.fs_count ?
6925184Sek110237 		    flowop->fo_stats.fs_mstate[FLOW_MSTATE_CPU] /
6935184Sek110237 		    (flowop->fo_stats.fs_count * 1000.0) : 0);
6945184Sek110237 
6955184Sek110237 		flowop = flowop->fo_next;
6965184Sek110237 	}
6975184Sek110237 	filebench_log(LOG_DUMP, "</cell_list>");
6985184Sek110237 
6995184Sek110237 	filebench_log(LOG_DUMP, "<dim_list>");
7005184Sek110237 	filebench_log(LOG_DUMP, "<dim>");
7015184Sek110237 	filebench_log(LOG_DUMP, "<dimval>Operations/sec</dimval>");
7025184Sek110237 	filebench_log(LOG_DUMP, "<dimval>MB/sec</dimval>");
7035184Sek110237 	filebench_log(LOG_DUMP, "<dimval>Latency (ms per operation)</dimval>");
7045184Sek110237 	filebench_log(LOG_DUMP, "<dimval>CPU (us per operation)</dimval>");
7055184Sek110237 	filebench_log(LOG_DUMP, "</dim>");
7065184Sek110237 
7075184Sek110237 	filebench_log(LOG_DUMP, "<dim>");
7086391Saw148015 	flowop = filebench_shm->shm_flowoplist;
7095184Sek110237 	while (flowop) {
7105184Sek110237 		if (flowop->fo_instance != FLOW_MASTER) {
7115184Sek110237 			flowop = flowop->fo_next;
7125184Sek110237 			continue;
7135184Sek110237 		}
7145184Sek110237 		filebench_log(LOG_DUMP, "<dimval>%s</dimval>", flowop->fo_name);
7155184Sek110237 		flowop = flowop->fo_next;
7165184Sek110237 	}
7175184Sek110237 	filebench_log(LOG_DUMP, "</dim>");
7185184Sek110237 	filebench_log(LOG_DUMP, "</dim_list>");
7195184Sek110237 	filebench_log(LOG_DUMP, "</stat_group>");
7205184Sek110237 
7215184Sek110237 	filebench_log(LOG_DUMP, "<stat_group name=\"IO Summary\">");
7225184Sek110237 	filebench_log(LOG_DUMP, "<cell_list>");
7235184Sek110237 	filebench_log(LOG_DUMP, "<cell>%0d</cell>",
7245184Sek110237 	    iostat->fs_count + aiostat->fs_count);
7255184Sek110237 	filebench_log(LOG_DUMP, "<cell>%0.1lf</cell>",
7265184Sek110237 	    (iostat->fs_count + aiostat->fs_count) /
7275184Sek110237 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS));
7285184Sek110237 	filebench_log(LOG_DUMP, "<cell>%0.0lf</cell>",
7295184Sek110237 	    (iostat->fs_rcount + aiostat->fs_rcount) /
7305184Sek110237 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS));
7315184Sek110237 	filebench_log(LOG_DUMP, "<cell>%0.0lf</cell>",
7325184Sek110237 	    (iostat->fs_wcount + aiostat->fs_wcount) /
7335184Sek110237 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS));
7345184Sek110237 	filebench_log(LOG_DUMP, "<cell>%0.1lf</cell>",
7355184Sek110237 	    ((iostat->fs_bytes + aiostat->fs_bytes) / (1024 * 1024)) /
7365184Sek110237 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS));
7375184Sek110237 	filebench_log(LOG_DUMP, "<cell>%0.0f</cell>",
7385184Sek110237 	    (iostat->fs_rcount + iostat->fs_wcount + aiostat->fs_rcount +
7395184Sek110237 	    aiostat->fs_wcount) ? (iostat->fs_syscpu / 1000.0) /
7405184Sek110237 	    (iostat->fs_rcount + iostat->fs_wcount + aiostat->fs_rcount +
7415184Sek110237 	    aiostat->fs_wcount) : 0);
7425184Sek110237 	filebench_log(LOG_DUMP, "</cell_list>");
7435184Sek110237 
7445184Sek110237 	filebench_log(LOG_DUMP, "<dim_list>");
7455184Sek110237 	filebench_log(LOG_DUMP, "<dim>");
7465184Sek110237 	filebench_log(LOG_DUMP, "<dimval>Operations</dimval>");
7475184Sek110237 	filebench_log(LOG_DUMP, "<dimval>Operations/sec</dimval>");
7485184Sek110237 	filebench_log(LOG_DUMP, "<dimval>Reads</dimval>");
7495184Sek110237 	filebench_log(LOG_DUMP, "<dimval>Writes</dimval>");
7505184Sek110237 	filebench_log(LOG_DUMP, "<dimval>MB/sec</dimval>");
7515184Sek110237 	filebench_log(LOG_DUMP, "<dimval>CPU (us per operation)</dimval>");
7525184Sek110237 	filebench_log(LOG_DUMP, "</dim>");
7535184Sek110237 
7545184Sek110237 	filebench_log(LOG_DUMP, "<dim>");
7555184Sek110237 	filebench_log(LOG_DUMP, "<dimval>IO Summary</dimval>");
7565184Sek110237 	filebench_log(LOG_DUMP, "</dim>");
7575184Sek110237 	filebench_log(LOG_DUMP, "</dim_list>");
7585184Sek110237 	filebench_log(LOG_DUMP, "</stat_group>");
7595184Sek110237 	filebench_log(LOG_DUMP, "</stat_doc>");
7605184Sek110237 }
7615184Sek110237 
7625184Sek110237 /*
763*7736SAndrew.W.Wilson@sun.com  * same as stats_dump, but in computer friendly format
764*7736SAndrew.W.Wilson@sun.com  */
765*7736SAndrew.W.Wilson@sun.com void
766*7736SAndrew.W.Wilson@sun.com stats_multidump(char *filename)
767*7736SAndrew.W.Wilson@sun.com {
768*7736SAndrew.W.Wilson@sun.com 	flowstat_t *iostat = &globalstats[FLOW_TYPE_IO];
769*7736SAndrew.W.Wilson@sun.com 	flowstat_t *aiostat = &globalstats[FLOW_TYPE_AIO];
770*7736SAndrew.W.Wilson@sun.com 	flowop_t *flowop;
771*7736SAndrew.W.Wilson@sun.com 
772*7736SAndrew.W.Wilson@sun.com 	/* don't dump stats if run ended in error */
773*7736SAndrew.W.Wilson@sun.com 	if (filebench_shm->shm_f_abort == FILEBENCH_ABORT_ERROR)
774*7736SAndrew.W.Wilson@sun.com 		return;
775*7736SAndrew.W.Wilson@sun.com 
776*7736SAndrew.W.Wilson@sun.com 	(void) strcpy(filebench_shm->shm_dump_filename, filename);
777*7736SAndrew.W.Wilson@sun.com 
778*7736SAndrew.W.Wilson@sun.com 	filebench_log(LOG_INFO, "in statsmultidump %s", filename);
779*7736SAndrew.W.Wilson@sun.com 
780*7736SAndrew.W.Wilson@sun.com 	if (filebench_shm->shm_dump_fd > 0) {
781*7736SAndrew.W.Wilson@sun.com 		(void) close(filebench_shm->shm_dump_fd);
782*7736SAndrew.W.Wilson@sun.com 		filebench_shm->shm_dump_fd = -1;
783*7736SAndrew.W.Wilson@sun.com 	}
784*7736SAndrew.W.Wilson@sun.com 
785*7736SAndrew.W.Wilson@sun.com 	filebench_log(LOG_DUMP, "Flowop totals:");
786*7736SAndrew.W.Wilson@sun.com 
787*7736SAndrew.W.Wilson@sun.com 	flowop = filebench_shm->shm_flowoplist;
788*7736SAndrew.W.Wilson@sun.com 	while (flowop) {
789*7736SAndrew.W.Wilson@sun.com 
790*7736SAndrew.W.Wilson@sun.com 		if (flowop->fo_instance != FLOW_MASTER) {
791*7736SAndrew.W.Wilson@sun.com 			flowop = flowop->fo_next;
792*7736SAndrew.W.Wilson@sun.com 			continue;
793*7736SAndrew.W.Wilson@sun.com 		}
794*7736SAndrew.W.Wilson@sun.com 
795*7736SAndrew.W.Wilson@sun.com 		filebench_log(LOG_DUMP,
796*7736SAndrew.W.Wilson@sun.com 		    "%s\t%1.0lf\t%1.1lf\t%1.1f\t%1.0f",
797*7736SAndrew.W.Wilson@sun.com 		    flowop->fo_name,
798*7736SAndrew.W.Wilson@sun.com 		    flowop->fo_stats.fs_count /
799*7736SAndrew.W.Wilson@sun.com 		    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
800*7736SAndrew.W.Wilson@sun.com 		    (flowop->fo_stats.fs_bytes / (1024 * 1024)) /
801*7736SAndrew.W.Wilson@sun.com 		    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
802*7736SAndrew.W.Wilson@sun.com 		    flowop->fo_stats.fs_count ?
803*7736SAndrew.W.Wilson@sun.com 		    flowop->fo_stats.fs_mstate[FLOW_MSTATE_LAT] /
804*7736SAndrew.W.Wilson@sun.com 		    (flowop->fo_stats.fs_count * 1000000.0) : 0,
805*7736SAndrew.W.Wilson@sun.com 		    flowop->fo_stats.fs_count ?
806*7736SAndrew.W.Wilson@sun.com 		    flowop->fo_stats.fs_mstate[FLOW_MSTATE_CPU] /
807*7736SAndrew.W.Wilson@sun.com 		    (flowop->fo_stats.fs_count * 1000.0) : 0);
808*7736SAndrew.W.Wilson@sun.com 
809*7736SAndrew.W.Wilson@sun.com 		flowop = flowop->fo_next;
810*7736SAndrew.W.Wilson@sun.com 	}
811*7736SAndrew.W.Wilson@sun.com 
812*7736SAndrew.W.Wilson@sun.com 	filebench_log(LOG_DUMP, "");
813*7736SAndrew.W.Wilson@sun.com 	filebench_log(LOG_DUMP,
814*7736SAndrew.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",
815*7736SAndrew.W.Wilson@sun.com 
816*7736SAndrew.W.Wilson@sun.com 	    iostat->fs_count + aiostat->fs_count,
817*7736SAndrew.W.Wilson@sun.com 
818*7736SAndrew.W.Wilson@sun.com 	    (iostat->fs_count + aiostat->fs_count) /
819*7736SAndrew.W.Wilson@sun.com 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
820*7736SAndrew.W.Wilson@sun.com 
821*7736SAndrew.W.Wilson@sun.com 	    (iostat->fs_rcount + aiostat->fs_rcount) /
822*7736SAndrew.W.Wilson@sun.com 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
823*7736SAndrew.W.Wilson@sun.com 
824*7736SAndrew.W.Wilson@sun.com 	    (iostat->fs_wcount + aiostat->fs_wcount) /
825*7736SAndrew.W.Wilson@sun.com 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
826*7736SAndrew.W.Wilson@sun.com 
827*7736SAndrew.W.Wilson@sun.com 	    ((iostat->fs_bytes + aiostat->fs_bytes) / (1024 * 1024)) /
828*7736SAndrew.W.Wilson@sun.com 	    ((globalstats->fs_etime - globalstats->fs_stime) / FSECS),
829*7736SAndrew.W.Wilson@sun.com 
830*7736SAndrew.W.Wilson@sun.com 	    (iostat->fs_rcount + iostat->fs_wcount +
831*7736SAndrew.W.Wilson@sun.com 	    aiostat->fs_rcount + aiostat->fs_wcount) ?
832*7736SAndrew.W.Wilson@sun.com 	    (iostat->fs_syscpu / 1000.0) /
833*7736SAndrew.W.Wilson@sun.com 	    (iostat->fs_rcount + iostat->fs_wcount +
834*7736SAndrew.W.Wilson@sun.com 	    aiostat->fs_rcount + aiostat->fs_wcount) : 0,
835*7736SAndrew.W.Wilson@sun.com 
836*7736SAndrew.W.Wilson@sun.com 	    (iostat->fs_rcount + iostat->fs_wcount) ?
837*7736SAndrew.W.Wilson@sun.com 	    iostat->fs_mstate[FLOW_MSTATE_LAT] /
838*7736SAndrew.W.Wilson@sun.com 	    ((iostat->fs_rcount + iostat->fs_wcount) * 1000000.0) : 0);
839*7736SAndrew.W.Wilson@sun.com }
840*7736SAndrew.W.Wilson@sun.com 
841*7736SAndrew.W.Wilson@sun.com /*
8425184Sek110237  * Clears all the statistics variables (fo_stats) for every defined flowop.
8435184Sek110237  * It also creates a global flowstat table if one doesn't already exist and
8445184Sek110237  * clears it.
8455184Sek110237  */
8465184Sek110237 void
8475184Sek110237 stats_clear(void)
8485184Sek110237 {
8495184Sek110237 	flowop_t *flowop;
8505184Sek110237 
8515184Sek110237 #ifdef HAVE_LIBKSTAT
8525184Sek110237 	stats_cputime = kstats_read_cpu();
8535184Sek110237 #else
8545184Sek110237 	stats_cputime = 0;
8555184Sek110237 #endif /* HAVE_LIBKSTAT */
8565184Sek110237 
8575184Sek110237 	if (globalstats == NULL)
8585184Sek110237 		globalstats = malloc(FLOW_TYPES * sizeof (flowstat_t));
8595184Sek110237 
8605184Sek110237 	(void) memset(globalstats, 0, FLOW_TYPES * sizeof (flowstat_t));
8615184Sek110237 
8626391Saw148015 	flowop = filebench_shm->shm_flowoplist;
8635184Sek110237 
8645184Sek110237 	while (flowop) {
8655184Sek110237 		filebench_log(LOG_DEBUG_IMPL, "Clearing stats for %s-%d",
8665184Sek110237 		    flowop->fo_name,
8675184Sek110237 		    flowop->fo_instance);
8685184Sek110237 		(void) memset(&flowop->fo_stats, 0, sizeof (flowstat_t));
8695184Sek110237 		flowop = flowop->fo_next;
8705184Sek110237 	}
8715184Sek110237 
8725184Sek110237 	(void) memset(globalstats, 0, sizeof (flowstat_t));
8735184Sek110237 	globalstats->fs_stime = gethrtime();
8745184Sek110237 }
875