1*716fd348SMartin Matuska#!/usr/bin/env @PYTHON_SHEBANG@ 2*716fd348SMartin Matuska# 3*716fd348SMartin Matuska# Print out ZFS ARC Statistics exported via kstat(1) 4*716fd348SMartin Matuska# For a definition of fields, or usage, use arcstat -v 5*716fd348SMartin Matuska# 6*716fd348SMartin Matuska# This script was originally a fork of the original arcstat.pl (0.1) 7*716fd348SMartin Matuska# by Neelakanth Nadgir, originally published on his Sun blog on 8*716fd348SMartin Matuska# 09/18/2007 9*716fd348SMartin Matuska# http://blogs.sun.com/realneel/entry/zfs_arc_statistics 10*716fd348SMartin Matuska# 11*716fd348SMartin Matuska# A new version aimed to improve upon the original by adding features 12*716fd348SMartin Matuska# and fixing bugs as needed. This version was maintained by Mike 13*716fd348SMartin Matuska# Harsch and was hosted in a public open source repository: 14*716fd348SMartin Matuska# http://github.com/mharsch/arcstat 15*716fd348SMartin Matuska# 16*716fd348SMartin Matuska# but has since moved to the illumos-gate repository. 17*716fd348SMartin Matuska# 18*716fd348SMartin Matuska# This Python port was written by John Hixson for FreeNAS, introduced 19*716fd348SMartin Matuska# in commit e2c29f: 20*716fd348SMartin Matuska# https://github.com/freenas/freenas 21*716fd348SMartin Matuska# 22*716fd348SMartin Matuska# and has been improved by many people since. 23*716fd348SMartin Matuska# 24*716fd348SMartin Matuska# CDDL HEADER START 25*716fd348SMartin Matuska# 26*716fd348SMartin Matuska# The contents of this file are subject to the terms of the 27*716fd348SMartin Matuska# Common Development and Distribution License, Version 1.0 only 28*716fd348SMartin Matuska# (the "License"). You may not use this file except in compliance 29*716fd348SMartin Matuska# with the License. 30*716fd348SMartin Matuska# 31*716fd348SMartin Matuska# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 32*716fd348SMartin Matuska# or http://www.opensolaris.org/os/licensing. 33*716fd348SMartin Matuska# See the License for the specific language governing permissions 34*716fd348SMartin Matuska# and limitations under the License. 35*716fd348SMartin Matuska# 36*716fd348SMartin Matuska# When distributing Covered Code, include this CDDL HEADER in each 37*716fd348SMartin Matuska# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 38*716fd348SMartin Matuska# If applicable, add the following below this CDDL HEADER, with the 39*716fd348SMartin Matuska# fields enclosed by brackets "[]" replaced with your own identifying 40*716fd348SMartin Matuska# information: Portions Copyright [yyyy] [name of copyright owner] 41*716fd348SMartin Matuska# 42*716fd348SMartin Matuska# CDDL HEADER END 43*716fd348SMartin Matuska# 44*716fd348SMartin Matuska# 45*716fd348SMartin Matuska# Fields have a fixed width. Every interval, we fill the "v" 46*716fd348SMartin Matuska# hash with its corresponding value (v[field]=value) using calculate(). 47*716fd348SMartin Matuska# @hdr is the array of fields that needs to be printed, so we 48*716fd348SMartin Matuska# just iterate over this array and print the values using our pretty printer. 49*716fd348SMartin Matuska# 50*716fd348SMartin Matuska# This script must remain compatible with Python 3.6+. 51*716fd348SMartin Matuska# 52*716fd348SMartin Matuska 53*716fd348SMartin Matuskaimport sys 54*716fd348SMartin Matuskaimport time 55*716fd348SMartin Matuskaimport getopt 56*716fd348SMartin Matuskaimport re 57*716fd348SMartin Matuskaimport copy 58*716fd348SMartin Matuska 59*716fd348SMartin Matuskafrom signal import signal, SIGINT, SIGWINCH, SIG_DFL 60*716fd348SMartin Matuska 61*716fd348SMartin Matuska 62*716fd348SMartin Matuskacols = { 63*716fd348SMartin Matuska # HDR: [Size, Scale, Description] 64*716fd348SMartin Matuska "time": [8, -1, "Time"], 65*716fd348SMartin Matuska "hits": [4, 1000, "ARC reads per second"], 66*716fd348SMartin Matuska "miss": [4, 1000, "ARC misses per second"], 67*716fd348SMartin Matuska "read": [4, 1000, "Total ARC accesses per second"], 68*716fd348SMartin Matuska "hit%": [4, 100, "ARC hit percentage"], 69*716fd348SMartin Matuska "miss%": [5, 100, "ARC miss percentage"], 70*716fd348SMartin Matuska "dhit": [4, 1000, "Demand hits per second"], 71*716fd348SMartin Matuska "dmis": [4, 1000, "Demand misses per second"], 72*716fd348SMartin Matuska "dh%": [3, 100, "Demand hit percentage"], 73*716fd348SMartin Matuska "dm%": [3, 100, "Demand miss percentage"], 74*716fd348SMartin Matuska "phit": [4, 1000, "Prefetch hits per second"], 75*716fd348SMartin Matuska "pmis": [4, 1000, "Prefetch misses per second"], 76*716fd348SMartin Matuska "ph%": [3, 100, "Prefetch hits percentage"], 77*716fd348SMartin Matuska "pm%": [3, 100, "Prefetch miss percentage"], 78*716fd348SMartin Matuska "mhit": [4, 1000, "Metadata hits per second"], 79*716fd348SMartin Matuska "mmis": [4, 1000, "Metadata misses per second"], 80*716fd348SMartin Matuska "mread": [5, 1000, "Metadata accesses per second"], 81*716fd348SMartin Matuska "mh%": [3, 100, "Metadata hit percentage"], 82*716fd348SMartin Matuska "mm%": [3, 100, "Metadata miss percentage"], 83*716fd348SMartin Matuska "arcsz": [5, 1024, "ARC size"], 84*716fd348SMartin Matuska "size": [4, 1024, "ARC size"], 85*716fd348SMartin Matuska "c": [4, 1024, "ARC target size"], 86*716fd348SMartin Matuska "mfu": [4, 1000, "MFU list hits per second"], 87*716fd348SMartin Matuska "mru": [4, 1000, "MRU list hits per second"], 88*716fd348SMartin Matuska "mfug": [4, 1000, "MFU ghost list hits per second"], 89*716fd348SMartin Matuska "mrug": [4, 1000, "MRU ghost list hits per second"], 90*716fd348SMartin Matuska "eskip": [5, 1000, "evict_skip per second"], 91*716fd348SMartin Matuska "el2skip": [7, 1000, "evict skip, due to l2 writes, per second"], 92*716fd348SMartin Matuska "el2cach": [7, 1024, "Size of L2 cached evictions per second"], 93*716fd348SMartin Matuska "el2el": [5, 1024, "Size of L2 eligible evictions per second"], 94*716fd348SMartin Matuska "el2mfu": [6, 1024, "Size of L2 eligible MFU evictions per second"], 95*716fd348SMartin Matuska "el2mru": [6, 1024, "Size of L2 eligible MRU evictions per second"], 96*716fd348SMartin Matuska "el2inel": [7, 1024, "Size of L2 ineligible evictions per second"], 97*716fd348SMartin Matuska "mtxmis": [6, 1000, "mutex_miss per second"], 98*716fd348SMartin Matuska "dread": [5, 1000, "Demand accesses per second"], 99*716fd348SMartin Matuska "pread": [5, 1000, "Prefetch accesses per second"], 100*716fd348SMartin Matuska "l2hits": [6, 1000, "L2ARC hits per second"], 101*716fd348SMartin Matuska "l2miss": [6, 1000, "L2ARC misses per second"], 102*716fd348SMartin Matuska "l2read": [6, 1000, "Total L2ARC accesses per second"], 103*716fd348SMartin Matuska "l2hit%": [6, 100, "L2ARC access hit percentage"], 104*716fd348SMartin Matuska "l2miss%": [7, 100, "L2ARC access miss percentage"], 105*716fd348SMartin Matuska "l2pref": [6, 1024, "L2ARC prefetch allocated size"], 106*716fd348SMartin Matuska "l2mfu": [5, 1024, "L2ARC MFU allocated size"], 107*716fd348SMartin Matuska "l2mru": [5, 1024, "L2ARC MRU allocated size"], 108*716fd348SMartin Matuska "l2data": [6, 1024, "L2ARC data allocated size"], 109*716fd348SMartin Matuska "l2meta": [6, 1024, "L2ARC metadata allocated size"], 110*716fd348SMartin Matuska "l2pref%": [7, 100, "L2ARC prefetch percentage"], 111*716fd348SMartin Matuska "l2mfu%": [6, 100, "L2ARC MFU percentage"], 112*716fd348SMartin Matuska "l2mru%": [6, 100, "L2ARC MRU percentage"], 113*716fd348SMartin Matuska "l2data%": [7, 100, "L2ARC data percentage"], 114*716fd348SMartin Matuska "l2meta%": [7, 100, "L2ARC metadata percentage"], 115*716fd348SMartin Matuska "l2asize": [7, 1024, "Actual (compressed) size of the L2ARC"], 116*716fd348SMartin Matuska "l2size": [6, 1024, "Size of the L2ARC"], 117*716fd348SMartin Matuska "l2bytes": [7, 1024, "Bytes read per second from the L2ARC"], 118*716fd348SMartin Matuska "grow": [4, 1000, "ARC grow disabled"], 119*716fd348SMartin Matuska "need": [4, 1024, "ARC reclaim need"], 120*716fd348SMartin Matuska "free": [4, 1024, "ARC free memory"], 121*716fd348SMartin Matuska "avail": [5, 1024, "ARC available memory"], 122*716fd348SMartin Matuska "waste": [5, 1024, "Wasted memory due to round up to pagesize"], 123*716fd348SMartin Matuska} 124*716fd348SMartin Matuska 125*716fd348SMartin Matuskav = {} 126*716fd348SMartin Matuskahdr = ["time", "read", "miss", "miss%", "dmis", "dm%", "pmis", "pm%", "mmis", 127*716fd348SMartin Matuska "mm%", "size", "c", "avail"] 128*716fd348SMartin Matuskaxhdr = ["time", "mfu", "mru", "mfug", "mrug", "eskip", "mtxmis", "dread", 129*716fd348SMartin Matuska "pread", "read"] 130*716fd348SMartin Matuskasint = 1 # Default interval is 1 second 131*716fd348SMartin Matuskacount = 1 # Default count is 1 132*716fd348SMartin Matuskahdr_intr = 20 # Print header every 20 lines of output 133*716fd348SMartin Matuskaopfile = None 134*716fd348SMartin Matuskasep = " " # Default separator is 2 spaces 135*716fd348SMartin Matuskaversion = "0.4" 136*716fd348SMartin Matuskal2exist = False 137*716fd348SMartin Matuskacmd = ("Usage: arcstat [-havxp] [-f fields] [-o file] [-s string] [interval " 138*716fd348SMartin Matuska "[count]]\n") 139*716fd348SMartin Matuskacur = {} 140*716fd348SMartin Matuskad = {} 141*716fd348SMartin Matuskaout = None 142*716fd348SMartin Matuskakstat = None 143*716fd348SMartin Matuskapretty_print = True 144*716fd348SMartin Matuska 145*716fd348SMartin Matuska 146*716fd348SMartin Matuskaif sys.platform.startswith('freebsd'): 147*716fd348SMartin Matuska # Requires py-sysctl on FreeBSD 148*716fd348SMartin Matuska import sysctl 149*716fd348SMartin Matuska 150*716fd348SMartin Matuska def kstat_update(): 151*716fd348SMartin Matuska global kstat 152*716fd348SMartin Matuska 153*716fd348SMartin Matuska k = [ctl for ctl in sysctl.filter('kstat.zfs.misc.arcstats') 154*716fd348SMartin Matuska if ctl.type != sysctl.CTLTYPE_NODE] 155*716fd348SMartin Matuska 156*716fd348SMartin Matuska if not k: 157*716fd348SMartin Matuska sys.exit(1) 158*716fd348SMartin Matuska 159*716fd348SMartin Matuska kstat = {} 160*716fd348SMartin Matuska 161*716fd348SMartin Matuska for s in k: 162*716fd348SMartin Matuska if not s: 163*716fd348SMartin Matuska continue 164*716fd348SMartin Matuska 165*716fd348SMartin Matuska name, value = s.name, s.value 166*716fd348SMartin Matuska # Trims 'kstat.zfs.misc.arcstats' from the name 167*716fd348SMartin Matuska kstat[name[24:]] = int(value) 168*716fd348SMartin Matuska 169*716fd348SMartin Matuskaelif sys.platform.startswith('linux'): 170*716fd348SMartin Matuska def kstat_update(): 171*716fd348SMartin Matuska global kstat 172*716fd348SMartin Matuska 173*716fd348SMartin Matuska k = [line.strip() for line in open('/proc/spl/kstat/zfs/arcstats')] 174*716fd348SMartin Matuska 175*716fd348SMartin Matuska if not k: 176*716fd348SMartin Matuska sys.exit(1) 177*716fd348SMartin Matuska 178*716fd348SMartin Matuska del k[0:2] 179*716fd348SMartin Matuska kstat = {} 180*716fd348SMartin Matuska 181*716fd348SMartin Matuska for s in k: 182*716fd348SMartin Matuska if not s: 183*716fd348SMartin Matuska continue 184*716fd348SMartin Matuska 185*716fd348SMartin Matuska name, unused, value = s.split() 186*716fd348SMartin Matuska kstat[name] = int(value) 187*716fd348SMartin Matuska 188*716fd348SMartin Matuska 189*716fd348SMartin Matuskadef detailed_usage(): 190*716fd348SMartin Matuska sys.stderr.write("%s\n" % cmd) 191*716fd348SMartin Matuska sys.stderr.write("Field definitions are as follows:\n") 192*716fd348SMartin Matuska for key in cols: 193*716fd348SMartin Matuska sys.stderr.write("%11s : %s\n" % (key, cols[key][2])) 194*716fd348SMartin Matuska sys.stderr.write("\n") 195*716fd348SMartin Matuska 196*716fd348SMartin Matuska sys.exit(0) 197*716fd348SMartin Matuska 198*716fd348SMartin Matuska 199*716fd348SMartin Matuskadef usage(): 200*716fd348SMartin Matuska sys.stderr.write("%s\n" % cmd) 201*716fd348SMartin Matuska sys.stderr.write("\t -h : Print this help message\n") 202*716fd348SMartin Matuska sys.stderr.write("\t -a : Print all possible stats\n") 203*716fd348SMartin Matuska sys.stderr.write("\t -v : List all possible field headers and definitions" 204*716fd348SMartin Matuska "\n") 205*716fd348SMartin Matuska sys.stderr.write("\t -x : Print extended stats\n") 206*716fd348SMartin Matuska sys.stderr.write("\t -f : Specify specific fields to print (see -v)\n") 207*716fd348SMartin Matuska sys.stderr.write("\t -o : Redirect output to the specified file\n") 208*716fd348SMartin Matuska sys.stderr.write("\t -s : Override default field separator with custom " 209*716fd348SMartin Matuska "character or string\n") 210*716fd348SMartin Matuska sys.stderr.write("\t -p : Disable auto-scaling of numerical fields\n") 211*716fd348SMartin Matuska sys.stderr.write("\nExamples:\n") 212*716fd348SMartin Matuska sys.stderr.write("\tarcstat -o /tmp/a.log 2 10\n") 213*716fd348SMartin Matuska sys.stderr.write("\tarcstat -s \",\" -o /tmp/a.log 2 10\n") 214*716fd348SMartin Matuska sys.stderr.write("\tarcstat -v\n") 215*716fd348SMartin Matuska sys.stderr.write("\tarcstat -f time,hit%,dh%,ph%,mh% 1\n") 216*716fd348SMartin Matuska sys.stderr.write("\n") 217*716fd348SMartin Matuska 218*716fd348SMartin Matuska sys.exit(1) 219*716fd348SMartin Matuska 220*716fd348SMartin Matuska 221*716fd348SMartin Matuskadef snap_stats(): 222*716fd348SMartin Matuska global cur 223*716fd348SMartin Matuska global kstat 224*716fd348SMartin Matuska 225*716fd348SMartin Matuska prev = copy.deepcopy(cur) 226*716fd348SMartin Matuska kstat_update() 227*716fd348SMartin Matuska 228*716fd348SMartin Matuska cur = kstat 229*716fd348SMartin Matuska for key in cur: 230*716fd348SMartin Matuska if re.match(key, "class"): 231*716fd348SMartin Matuska continue 232*716fd348SMartin Matuska if key in prev: 233*716fd348SMartin Matuska d[key] = cur[key] - prev[key] 234*716fd348SMartin Matuska else: 235*716fd348SMartin Matuska d[key] = cur[key] 236*716fd348SMartin Matuska 237*716fd348SMartin Matuska 238*716fd348SMartin Matuskadef prettynum(sz, scale, num=0): 239*716fd348SMartin Matuska suffix = [' ', 'K', 'M', 'G', 'T', 'P', 'E', 'Z'] 240*716fd348SMartin Matuska index = 0 241*716fd348SMartin Matuska save = 0 242*716fd348SMartin Matuska 243*716fd348SMartin Matuska # Special case for date field 244*716fd348SMartin Matuska if scale == -1: 245*716fd348SMartin Matuska return "%s" % num 246*716fd348SMartin Matuska 247*716fd348SMartin Matuska # Rounding error, return 0 248*716fd348SMartin Matuska elif 0 < num < 1: 249*716fd348SMartin Matuska num = 0 250*716fd348SMartin Matuska 251*716fd348SMartin Matuska while abs(num) > scale and index < 5: 252*716fd348SMartin Matuska save = num 253*716fd348SMartin Matuska num = num / scale 254*716fd348SMartin Matuska index += 1 255*716fd348SMartin Matuska 256*716fd348SMartin Matuska if index == 0: 257*716fd348SMartin Matuska return "%*d" % (sz, num) 258*716fd348SMartin Matuska 259*716fd348SMartin Matuska if abs(save / scale) < 10: 260*716fd348SMartin Matuska return "%*.1f%s" % (sz - 1, num, suffix[index]) 261*716fd348SMartin Matuska else: 262*716fd348SMartin Matuska return "%*d%s" % (sz - 1, num, suffix[index]) 263*716fd348SMartin Matuska 264*716fd348SMartin Matuska 265*716fd348SMartin Matuskadef print_values(): 266*716fd348SMartin Matuska global hdr 267*716fd348SMartin Matuska global sep 268*716fd348SMartin Matuska global v 269*716fd348SMartin Matuska global pretty_print 270*716fd348SMartin Matuska 271*716fd348SMartin Matuska if pretty_print: 272*716fd348SMartin Matuska fmt = lambda col: prettynum(cols[col][0], cols[col][1], v[col]) 273*716fd348SMartin Matuska else: 274*716fd348SMartin Matuska fmt = lambda col: v[col] 275*716fd348SMartin Matuska 276*716fd348SMartin Matuska sys.stdout.write(sep.join(fmt(col) for col in hdr)) 277*716fd348SMartin Matuska sys.stdout.write("\n") 278*716fd348SMartin Matuska sys.stdout.flush() 279*716fd348SMartin Matuska 280*716fd348SMartin Matuska 281*716fd348SMartin Matuskadef print_header(): 282*716fd348SMartin Matuska global hdr 283*716fd348SMartin Matuska global sep 284*716fd348SMartin Matuska global pretty_print 285*716fd348SMartin Matuska 286*716fd348SMartin Matuska if pretty_print: 287*716fd348SMartin Matuska fmt = lambda col: "%*s" % (cols[col][0], col) 288*716fd348SMartin Matuska else: 289*716fd348SMartin Matuska fmt = lambda col: col 290*716fd348SMartin Matuska 291*716fd348SMartin Matuska sys.stdout.write(sep.join(fmt(col) for col in hdr)) 292*716fd348SMartin Matuska sys.stdout.write("\n") 293*716fd348SMartin Matuska 294*716fd348SMartin Matuska 295*716fd348SMartin Matuskadef get_terminal_lines(): 296*716fd348SMartin Matuska try: 297*716fd348SMartin Matuska import fcntl 298*716fd348SMartin Matuska import termios 299*716fd348SMartin Matuska import struct 300*716fd348SMartin Matuska data = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, '1234') 301*716fd348SMartin Matuska sz = struct.unpack('hh', data) 302*716fd348SMartin Matuska return sz[0] 303*716fd348SMartin Matuska except Exception: 304*716fd348SMartin Matuska pass 305*716fd348SMartin Matuska 306*716fd348SMartin Matuska 307*716fd348SMartin Matuskadef update_hdr_intr(): 308*716fd348SMartin Matuska global hdr_intr 309*716fd348SMartin Matuska 310*716fd348SMartin Matuska lines = get_terminal_lines() 311*716fd348SMartin Matuska if lines and lines > 3: 312*716fd348SMartin Matuska hdr_intr = lines - 3 313*716fd348SMartin Matuska 314*716fd348SMartin Matuska 315*716fd348SMartin Matuskadef resize_handler(signum, frame): 316*716fd348SMartin Matuska update_hdr_intr() 317*716fd348SMartin Matuska 318*716fd348SMartin Matuska 319*716fd348SMartin Matuskadef init(): 320*716fd348SMartin Matuska global sint 321*716fd348SMartin Matuska global count 322*716fd348SMartin Matuska global hdr 323*716fd348SMartin Matuska global xhdr 324*716fd348SMartin Matuska global opfile 325*716fd348SMartin Matuska global sep 326*716fd348SMartin Matuska global out 327*716fd348SMartin Matuska global l2exist 328*716fd348SMartin Matuska global pretty_print 329*716fd348SMartin Matuska 330*716fd348SMartin Matuska desired_cols = None 331*716fd348SMartin Matuska aflag = False 332*716fd348SMartin Matuska xflag = False 333*716fd348SMartin Matuska hflag = False 334*716fd348SMartin Matuska vflag = False 335*716fd348SMartin Matuska i = 1 336*716fd348SMartin Matuska 337*716fd348SMartin Matuska try: 338*716fd348SMartin Matuska opts, args = getopt.getopt( 339*716fd348SMartin Matuska sys.argv[1:], 340*716fd348SMartin Matuska "axo:hvs:f:p", 341*716fd348SMartin Matuska [ 342*716fd348SMartin Matuska "all", 343*716fd348SMartin Matuska "extended", 344*716fd348SMartin Matuska "outfile", 345*716fd348SMartin Matuska "help", 346*716fd348SMartin Matuska "verbose", 347*716fd348SMartin Matuska "separator", 348*716fd348SMartin Matuska "columns", 349*716fd348SMartin Matuska "parsable" 350*716fd348SMartin Matuska ] 351*716fd348SMartin Matuska ) 352*716fd348SMartin Matuska except getopt.error as msg: 353*716fd348SMartin Matuska sys.stderr.write("Error: %s\n" % str(msg)) 354*716fd348SMartin Matuska usage() 355*716fd348SMartin Matuska opts = None 356*716fd348SMartin Matuska 357*716fd348SMartin Matuska for opt, arg in opts: 358*716fd348SMartin Matuska if opt in ('-a', '--all'): 359*716fd348SMartin Matuska aflag = True 360*716fd348SMartin Matuska if opt in ('-x', '--extended'): 361*716fd348SMartin Matuska xflag = True 362*716fd348SMartin Matuska if opt in ('-o', '--outfile'): 363*716fd348SMartin Matuska opfile = arg 364*716fd348SMartin Matuska i += 1 365*716fd348SMartin Matuska if opt in ('-h', '--help'): 366*716fd348SMartin Matuska hflag = True 367*716fd348SMartin Matuska if opt in ('-v', '--verbose'): 368*716fd348SMartin Matuska vflag = True 369*716fd348SMartin Matuska if opt in ('-s', '--separator'): 370*716fd348SMartin Matuska sep = arg 371*716fd348SMartin Matuska i += 1 372*716fd348SMartin Matuska if opt in ('-f', '--columns'): 373*716fd348SMartin Matuska desired_cols = arg 374*716fd348SMartin Matuska i += 1 375*716fd348SMartin Matuska if opt in ('-p', '--parsable'): 376*716fd348SMartin Matuska pretty_print = False 377*716fd348SMartin Matuska i += 1 378*716fd348SMartin Matuska 379*716fd348SMartin Matuska argv = sys.argv[i:] 380*716fd348SMartin Matuska sint = int(argv[0]) if argv else sint 381*716fd348SMartin Matuska count = int(argv[1]) if len(argv) > 1 else (0 if len(argv) > 0 else 1) 382*716fd348SMartin Matuska 383*716fd348SMartin Matuska if hflag or (xflag and desired_cols): 384*716fd348SMartin Matuska usage() 385*716fd348SMartin Matuska 386*716fd348SMartin Matuska if vflag: 387*716fd348SMartin Matuska detailed_usage() 388*716fd348SMartin Matuska 389*716fd348SMartin Matuska if xflag: 390*716fd348SMartin Matuska hdr = xhdr 391*716fd348SMartin Matuska 392*716fd348SMartin Matuska update_hdr_intr() 393*716fd348SMartin Matuska 394*716fd348SMartin Matuska # check if L2ARC exists 395*716fd348SMartin Matuska snap_stats() 396*716fd348SMartin Matuska l2_size = cur.get("l2_size") 397*716fd348SMartin Matuska if l2_size: 398*716fd348SMartin Matuska l2exist = True 399*716fd348SMartin Matuska 400*716fd348SMartin Matuska if desired_cols: 401*716fd348SMartin Matuska hdr = desired_cols.split(",") 402*716fd348SMartin Matuska 403*716fd348SMartin Matuska invalid = [] 404*716fd348SMartin Matuska incompat = [] 405*716fd348SMartin Matuska for ele in hdr: 406*716fd348SMartin Matuska if ele not in cols: 407*716fd348SMartin Matuska invalid.append(ele) 408*716fd348SMartin Matuska elif not l2exist and ele.startswith("l2"): 409*716fd348SMartin Matuska sys.stdout.write("No L2ARC Here\n%s\n" % ele) 410*716fd348SMartin Matuska incompat.append(ele) 411*716fd348SMartin Matuska 412*716fd348SMartin Matuska if len(invalid) > 0: 413*716fd348SMartin Matuska sys.stderr.write("Invalid column definition! -- %s\n" % invalid) 414*716fd348SMartin Matuska usage() 415*716fd348SMartin Matuska 416*716fd348SMartin Matuska if len(incompat) > 0: 417*716fd348SMartin Matuska sys.stderr.write("Incompatible field specified! -- %s\n" % 418*716fd348SMartin Matuska incompat) 419*716fd348SMartin Matuska usage() 420*716fd348SMartin Matuska 421*716fd348SMartin Matuska if aflag: 422*716fd348SMartin Matuska if l2exist: 423*716fd348SMartin Matuska hdr = cols.keys() 424*716fd348SMartin Matuska else: 425*716fd348SMartin Matuska hdr = [col for col in cols.keys() if not col.startswith("l2")] 426*716fd348SMartin Matuska 427*716fd348SMartin Matuska if opfile: 428*716fd348SMartin Matuska try: 429*716fd348SMartin Matuska out = open(opfile, "w") 430*716fd348SMartin Matuska sys.stdout = out 431*716fd348SMartin Matuska 432*716fd348SMartin Matuska except IOError: 433*716fd348SMartin Matuska sys.stderr.write("Cannot open %s for writing\n" % opfile) 434*716fd348SMartin Matuska sys.exit(1) 435*716fd348SMartin Matuska 436*716fd348SMartin Matuska 437*716fd348SMartin Matuskadef calculate(): 438*716fd348SMartin Matuska global d 439*716fd348SMartin Matuska global v 440*716fd348SMartin Matuska global l2exist 441*716fd348SMartin Matuska 442*716fd348SMartin Matuska v = dict() 443*716fd348SMartin Matuska v["time"] = time.strftime("%H:%M:%S", time.localtime()) 444*716fd348SMartin Matuska v["hits"] = d["hits"] // sint 445*716fd348SMartin Matuska v["miss"] = d["misses"] // sint 446*716fd348SMartin Matuska v["read"] = v["hits"] + v["miss"] 447*716fd348SMartin Matuska v["hit%"] = 100 * v["hits"] // v["read"] if v["read"] > 0 else 0 448*716fd348SMartin Matuska v["miss%"] = 100 - v["hit%"] if v["read"] > 0 else 0 449*716fd348SMartin Matuska 450*716fd348SMartin Matuska v["dhit"] = (d["demand_data_hits"] + d["demand_metadata_hits"]) // sint 451*716fd348SMartin Matuska v["dmis"] = (d["demand_data_misses"] + d["demand_metadata_misses"]) // sint 452*716fd348SMartin Matuska 453*716fd348SMartin Matuska v["dread"] = v["dhit"] + v["dmis"] 454*716fd348SMartin Matuska v["dh%"] = 100 * v["dhit"] // v["dread"] if v["dread"] > 0 else 0 455*716fd348SMartin Matuska v["dm%"] = 100 - v["dh%"] if v["dread"] > 0 else 0 456*716fd348SMartin Matuska 457*716fd348SMartin Matuska v["phit"] = (d["prefetch_data_hits"] + d["prefetch_metadata_hits"]) // sint 458*716fd348SMartin Matuska v["pmis"] = (d["prefetch_data_misses"] + 459*716fd348SMartin Matuska d["prefetch_metadata_misses"]) // sint 460*716fd348SMartin Matuska 461*716fd348SMartin Matuska v["pread"] = v["phit"] + v["pmis"] 462*716fd348SMartin Matuska v["ph%"] = 100 * v["phit"] // v["pread"] if v["pread"] > 0 else 0 463*716fd348SMartin Matuska v["pm%"] = 100 - v["ph%"] if v["pread"] > 0 else 0 464*716fd348SMartin Matuska 465*716fd348SMartin Matuska v["mhit"] = (d["prefetch_metadata_hits"] + 466*716fd348SMartin Matuska d["demand_metadata_hits"]) // sint 467*716fd348SMartin Matuska v["mmis"] = (d["prefetch_metadata_misses"] + 468*716fd348SMartin Matuska d["demand_metadata_misses"]) // sint 469*716fd348SMartin Matuska 470*716fd348SMartin Matuska v["mread"] = v["mhit"] + v["mmis"] 471*716fd348SMartin Matuska v["mh%"] = 100 * v["mhit"] // v["mread"] if v["mread"] > 0 else 0 472*716fd348SMartin Matuska v["mm%"] = 100 - v["mh%"] if v["mread"] > 0 else 0 473*716fd348SMartin Matuska 474*716fd348SMartin Matuska v["arcsz"] = cur["size"] 475*716fd348SMartin Matuska v["size"] = cur["size"] 476*716fd348SMartin Matuska v["c"] = cur["c"] 477*716fd348SMartin Matuska v["mfu"] = d["mfu_hits"] // sint 478*716fd348SMartin Matuska v["mru"] = d["mru_hits"] // sint 479*716fd348SMartin Matuska v["mrug"] = d["mru_ghost_hits"] // sint 480*716fd348SMartin Matuska v["mfug"] = d["mfu_ghost_hits"] // sint 481*716fd348SMartin Matuska v["eskip"] = d["evict_skip"] // sint 482*716fd348SMartin Matuska v["el2skip"] = d["evict_l2_skip"] // sint 483*716fd348SMartin Matuska v["el2cach"] = d["evict_l2_cached"] // sint 484*716fd348SMartin Matuska v["el2el"] = d["evict_l2_eligible"] // sint 485*716fd348SMartin Matuska v["el2mfu"] = d["evict_l2_eligible_mfu"] // sint 486*716fd348SMartin Matuska v["el2mru"] = d["evict_l2_eligible_mru"] // sint 487*716fd348SMartin Matuska v["el2inel"] = d["evict_l2_ineligible"] // sint 488*716fd348SMartin Matuska v["mtxmis"] = d["mutex_miss"] // sint 489*716fd348SMartin Matuska 490*716fd348SMartin Matuska if l2exist: 491*716fd348SMartin Matuska v["l2hits"] = d["l2_hits"] // sint 492*716fd348SMartin Matuska v["l2miss"] = d["l2_misses"] // sint 493*716fd348SMartin Matuska v["l2read"] = v["l2hits"] + v["l2miss"] 494*716fd348SMartin Matuska v["l2hit%"] = 100 * v["l2hits"] // v["l2read"] if v["l2read"] > 0 else 0 495*716fd348SMartin Matuska 496*716fd348SMartin Matuska v["l2miss%"] = 100 - v["l2hit%"] if v["l2read"] > 0 else 0 497*716fd348SMartin Matuska v["l2asize"] = cur["l2_asize"] 498*716fd348SMartin Matuska v["l2size"] = cur["l2_size"] 499*716fd348SMartin Matuska v["l2bytes"] = d["l2_read_bytes"] // sint 500*716fd348SMartin Matuska 501*716fd348SMartin Matuska v["l2pref"] = cur["l2_prefetch_asize"] 502*716fd348SMartin Matuska v["l2mfu"] = cur["l2_mfu_asize"] 503*716fd348SMartin Matuska v["l2mru"] = cur["l2_mru_asize"] 504*716fd348SMartin Matuska v["l2data"] = cur["l2_bufc_data_asize"] 505*716fd348SMartin Matuska v["l2meta"] = cur["l2_bufc_metadata_asize"] 506*716fd348SMartin Matuska v["l2pref%"] = 100 * v["l2pref"] // v["l2asize"] 507*716fd348SMartin Matuska v["l2mfu%"] = 100 * v["l2mfu"] // v["l2asize"] 508*716fd348SMartin Matuska v["l2mru%"] = 100 * v["l2mru"] // v["l2asize"] 509*716fd348SMartin Matuska v["l2data%"] = 100 * v["l2data"] // v["l2asize"] 510*716fd348SMartin Matuska v["l2meta%"] = 100 * v["l2meta"] // v["l2asize"] 511*716fd348SMartin Matuska 512*716fd348SMartin Matuska v["grow"] = 0 if cur["arc_no_grow"] else 1 513*716fd348SMartin Matuska v["need"] = cur["arc_need_free"] 514*716fd348SMartin Matuska v["free"] = cur["memory_free_bytes"] 515*716fd348SMartin Matuska v["avail"] = cur["memory_available_bytes"] 516*716fd348SMartin Matuska v["waste"] = cur["abd_chunk_waste_size"] 517*716fd348SMartin Matuska 518*716fd348SMartin Matuska 519*716fd348SMartin Matuskadef main(): 520*716fd348SMartin Matuska global sint 521*716fd348SMartin Matuska global count 522*716fd348SMartin Matuska global hdr_intr 523*716fd348SMartin Matuska 524*716fd348SMartin Matuska i = 0 525*716fd348SMartin Matuska count_flag = 0 526*716fd348SMartin Matuska 527*716fd348SMartin Matuska init() 528*716fd348SMartin Matuska if count > 0: 529*716fd348SMartin Matuska count_flag = 1 530*716fd348SMartin Matuska 531*716fd348SMartin Matuska signal(SIGINT, SIG_DFL) 532*716fd348SMartin Matuska signal(SIGWINCH, resize_handler) 533*716fd348SMartin Matuska while True: 534*716fd348SMartin Matuska if i == 0: 535*716fd348SMartin Matuska print_header() 536*716fd348SMartin Matuska 537*716fd348SMartin Matuska snap_stats() 538*716fd348SMartin Matuska calculate() 539*716fd348SMartin Matuska print_values() 540*716fd348SMartin Matuska 541*716fd348SMartin Matuska if count_flag == 1: 542*716fd348SMartin Matuska if count <= 1: 543*716fd348SMartin Matuska break 544*716fd348SMartin Matuska count -= 1 545*716fd348SMartin Matuska 546*716fd348SMartin Matuska i = 0 if i >= hdr_intr else i + 1 547*716fd348SMartin Matuska time.sleep(sint) 548*716fd348SMartin Matuska 549*716fd348SMartin Matuska if out: 550*716fd348SMartin Matuska out.close() 551*716fd348SMartin Matuska 552*716fd348SMartin Matuska 553*716fd348SMartin Matuskaif __name__ == '__main__': 554*716fd348SMartin Matuska main() 555