1716fd348SMartin Matuska#!/usr/bin/env @PYTHON_SHEBANG@ 2716fd348SMartin Matuska# 3716fd348SMartin Matuska# Print out ZFS ARC Statistics exported via kstat(1) 4716fd348SMartin Matuska# For a definition of fields, or usage, use arcstat -v 5716fd348SMartin Matuska# 6716fd348SMartin Matuska# This script was originally a fork of the original arcstat.pl (0.1) 7716fd348SMartin Matuska# by Neelakanth Nadgir, originally published on his Sun blog on 8716fd348SMartin Matuska# 09/18/2007 9716fd348SMartin Matuska# http://blogs.sun.com/realneel/entry/zfs_arc_statistics 10716fd348SMartin Matuska# 11716fd348SMartin Matuska# A new version aimed to improve upon the original by adding features 12716fd348SMartin Matuska# and fixing bugs as needed. This version was maintained by Mike 13716fd348SMartin Matuska# Harsch and was hosted in a public open source repository: 14716fd348SMartin Matuska# http://github.com/mharsch/arcstat 15716fd348SMartin Matuska# 16716fd348SMartin Matuska# but has since moved to the illumos-gate repository. 17716fd348SMartin Matuska# 18716fd348SMartin Matuska# This Python port was written by John Hixson for FreeNAS, introduced 19716fd348SMartin Matuska# in commit e2c29f: 20716fd348SMartin Matuska# https://github.com/freenas/freenas 21716fd348SMartin Matuska# 22716fd348SMartin Matuska# and has been improved by many people since. 23716fd348SMartin Matuska# 24716fd348SMartin Matuska# CDDL HEADER START 25716fd348SMartin Matuska# 26716fd348SMartin Matuska# The contents of this file are subject to the terms of the 27716fd348SMartin Matuska# Common Development and Distribution License, Version 1.0 only 28716fd348SMartin Matuska# (the "License"). You may not use this file except in compliance 29716fd348SMartin Matuska# with the License. 30716fd348SMartin Matuska# 31716fd348SMartin Matuska# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 32271171e0SMartin Matuska# or https://opensource.org/licenses/CDDL-1.0. 33716fd348SMartin Matuska# See the License for the specific language governing permissions 34716fd348SMartin Matuska# and limitations under the License. 35716fd348SMartin Matuska# 36716fd348SMartin Matuska# When distributing Covered Code, include this CDDL HEADER in each 37716fd348SMartin Matuska# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 38716fd348SMartin Matuska# If applicable, add the following below this CDDL HEADER, with the 39716fd348SMartin Matuska# fields enclosed by brackets "[]" replaced with your own identifying 40716fd348SMartin Matuska# information: Portions Copyright [yyyy] [name of copyright owner] 41716fd348SMartin Matuska# 42716fd348SMartin Matuska# CDDL HEADER END 43716fd348SMartin Matuska# 44716fd348SMartin Matuska# 45716fd348SMartin Matuska# Fields have a fixed width. Every interval, we fill the "v" 46716fd348SMartin Matuska# hash with its corresponding value (v[field]=value) using calculate(). 47716fd348SMartin Matuska# @hdr is the array of fields that needs to be printed, so we 48716fd348SMartin Matuska# just iterate over this array and print the values using our pretty printer. 49716fd348SMartin Matuska# 50716fd348SMartin Matuska# This script must remain compatible with Python 3.6+. 51716fd348SMartin Matuska# 52716fd348SMartin Matuska 53716fd348SMartin Matuskaimport sys 54716fd348SMartin Matuskaimport time 55716fd348SMartin Matuskaimport getopt 56716fd348SMartin Matuskaimport re 57716fd348SMartin Matuskaimport copy 58716fd348SMartin Matuska 59716fd348SMartin Matuskafrom signal import signal, SIGINT, SIGWINCH, SIG_DFL 60716fd348SMartin Matuska 61716fd348SMartin Matuska 62716fd348SMartin Matuskacols = { 63716fd348SMartin Matuska # HDR: [Size, Scale, Description] 64716fd348SMartin Matuska "time": [8, -1, "Time"], 6515f0b8c3SMartin Matuska "hits": [4, 1000, "ARC hits per second"], 6615f0b8c3SMartin Matuska "iohs": [4, 1000, "ARC I/O hits per second"], 67716fd348SMartin Matuska "miss": [4, 1000, "ARC misses per second"], 68716fd348SMartin Matuska "read": [4, 1000, "Total ARC accesses per second"], 69716fd348SMartin Matuska "hit%": [4, 100, "ARC hit percentage"], 7015f0b8c3SMartin Matuska "ioh%": [4, 100, "ARC I/O hit percentage"], 71716fd348SMartin Matuska "miss%": [5, 100, "ARC miss percentage"], 72716fd348SMartin Matuska "dhit": [4, 1000, "Demand hits per second"], 7315f0b8c3SMartin Matuska "dioh": [4, 1000, "Demand I/O hits per second"], 74716fd348SMartin Matuska "dmis": [4, 1000, "Demand misses per second"], 75716fd348SMartin Matuska "dh%": [3, 100, "Demand hit percentage"], 7615f0b8c3SMartin Matuska "di%": [3, 100, "Demand I/O hit percentage"], 77716fd348SMartin Matuska "dm%": [3, 100, "Demand miss percentage"], 7815f0b8c3SMartin Matuska "ddhit": [5, 1000, "Demand data hits per second"], 7915f0b8c3SMartin Matuska "ddioh": [5, 1000, "Demand data I/O hits per second"], 8015f0b8c3SMartin Matuska "ddmis": [5, 1000, "Demand data misses per second"], 8115f0b8c3SMartin Matuska "ddh%": [4, 100, "Demand data hit percentage"], 8215f0b8c3SMartin Matuska "ddi%": [4, 100, "Demand data I/O hit percentage"], 8315f0b8c3SMartin Matuska "ddm%": [4, 100, "Demand data miss percentage"], 8415f0b8c3SMartin Matuska "dmhit": [5, 1000, "Demand metadata hits per second"], 8515f0b8c3SMartin Matuska "dmioh": [5, 1000, "Demand metadata I/O hits per second"], 8615f0b8c3SMartin Matuska "dmmis": [5, 1000, "Demand metadata misses per second"], 8715f0b8c3SMartin Matuska "dmh%": [4, 100, "Demand metadata hit percentage"], 8815f0b8c3SMartin Matuska "dmi%": [4, 100, "Demand metadata I/O hit percentage"], 8915f0b8c3SMartin Matuska "dmm%": [4, 100, "Demand metadata miss percentage"], 90716fd348SMartin Matuska "phit": [4, 1000, "Prefetch hits per second"], 9115f0b8c3SMartin Matuska "pioh": [4, 1000, "Prefetch I/O hits per second"], 92716fd348SMartin Matuska "pmis": [4, 1000, "Prefetch misses per second"], 93716fd348SMartin Matuska "ph%": [3, 100, "Prefetch hits percentage"], 9415f0b8c3SMartin Matuska "pi%": [3, 100, "Prefetch I/O hits percentage"], 95716fd348SMartin Matuska "pm%": [3, 100, "Prefetch miss percentage"], 9615f0b8c3SMartin Matuska "pdhit": [5, 1000, "Prefetch data hits per second"], 9715f0b8c3SMartin Matuska "pdioh": [5, 1000, "Prefetch data I/O hits per second"], 9815f0b8c3SMartin Matuska "pdmis": [5, 1000, "Prefetch data misses per second"], 9915f0b8c3SMartin Matuska "pdh%": [4, 100, "Prefetch data hits percentage"], 10015f0b8c3SMartin Matuska "pdi%": [4, 100, "Prefetch data I/O hits percentage"], 10115f0b8c3SMartin Matuska "pdm%": [4, 100, "Prefetch data miss percentage"], 10215f0b8c3SMartin Matuska "pmhit": [5, 1000, "Prefetch metadata hits per second"], 10315f0b8c3SMartin Matuska "pmioh": [5, 1000, "Prefetch metadata I/O hits per second"], 10415f0b8c3SMartin Matuska "pmmis": [5, 1000, "Prefetch metadata misses per second"], 10515f0b8c3SMartin Matuska "pmh%": [4, 100, "Prefetch metadata hits percentage"], 10615f0b8c3SMartin Matuska "pmi%": [4, 100, "Prefetch metadata I/O hits percentage"], 10715f0b8c3SMartin Matuska "pmm%": [4, 100, "Prefetch metadata miss percentage"], 108716fd348SMartin Matuska "mhit": [4, 1000, "Metadata hits per second"], 10915f0b8c3SMartin Matuska "mioh": [4, 1000, "Metadata I/O hits per second"], 110716fd348SMartin Matuska "mmis": [4, 1000, "Metadata misses per second"], 111716fd348SMartin Matuska "mread": [5, 1000, "Metadata accesses per second"], 112716fd348SMartin Matuska "mh%": [3, 100, "Metadata hit percentage"], 11315f0b8c3SMartin Matuska "mi%": [3, 100, "Metadata I/O hit percentage"], 114716fd348SMartin Matuska "mm%": [3, 100, "Metadata miss percentage"], 115716fd348SMartin Matuska "arcsz": [5, 1024, "ARC size"], 11615f0b8c3SMartin Matuska "size": [5, 1024, "ARC size"], 11715f0b8c3SMartin Matuska "c": [5, 1024, "ARC target size"], 118716fd348SMartin Matuska "mfu": [4, 1000, "MFU list hits per second"], 119716fd348SMartin Matuska "mru": [4, 1000, "MRU list hits per second"], 120716fd348SMartin Matuska "mfug": [4, 1000, "MFU ghost list hits per second"], 121716fd348SMartin Matuska "mrug": [4, 1000, "MRU ghost list hits per second"], 12215f0b8c3SMartin Matuska "unc": [4, 1000, "Uncached list hits per second"], 123716fd348SMartin Matuska "eskip": [5, 1000, "evict_skip per second"], 124716fd348SMartin Matuska "el2skip": [7, 1000, "evict skip, due to l2 writes, per second"], 125716fd348SMartin Matuska "el2cach": [7, 1024, "Size of L2 cached evictions per second"], 126716fd348SMartin Matuska "el2el": [5, 1024, "Size of L2 eligible evictions per second"], 127716fd348SMartin Matuska "el2mfu": [6, 1024, "Size of L2 eligible MFU evictions per second"], 128716fd348SMartin Matuska "el2mru": [6, 1024, "Size of L2 eligible MRU evictions per second"], 129716fd348SMartin Matuska "el2inel": [7, 1024, "Size of L2 ineligible evictions per second"], 130716fd348SMartin Matuska "mtxmis": [6, 1000, "mutex_miss per second"], 131716fd348SMartin Matuska "dread": [5, 1000, "Demand accesses per second"], 13215f0b8c3SMartin Matuska "ddread": [6, 1000, "Demand data accesses per second"], 13315f0b8c3SMartin Matuska "dmread": [6, 1000, "Demand metadata accesses per second"], 134716fd348SMartin Matuska "pread": [5, 1000, "Prefetch accesses per second"], 13515f0b8c3SMartin Matuska "pdread": [6, 1000, "Prefetch data accesses per second"], 13615f0b8c3SMartin Matuska "pmread": [6, 1000, "Prefetch metadata accesses per second"], 137716fd348SMartin Matuska "l2hits": [6, 1000, "L2ARC hits per second"], 138716fd348SMartin Matuska "l2miss": [6, 1000, "L2ARC misses per second"], 139716fd348SMartin Matuska "l2read": [6, 1000, "Total L2ARC accesses per second"], 140716fd348SMartin Matuska "l2hit%": [6, 100, "L2ARC access hit percentage"], 141716fd348SMartin Matuska "l2miss%": [7, 100, "L2ARC access miss percentage"], 142716fd348SMartin Matuska "l2pref": [6, 1024, "L2ARC prefetch allocated size"], 143716fd348SMartin Matuska "l2mfu": [5, 1024, "L2ARC MFU allocated size"], 144716fd348SMartin Matuska "l2mru": [5, 1024, "L2ARC MRU allocated size"], 145716fd348SMartin Matuska "l2data": [6, 1024, "L2ARC data allocated size"], 146716fd348SMartin Matuska "l2meta": [6, 1024, "L2ARC metadata allocated size"], 147716fd348SMartin Matuska "l2pref%": [7, 100, "L2ARC prefetch percentage"], 148716fd348SMartin Matuska "l2mfu%": [6, 100, "L2ARC MFU percentage"], 149716fd348SMartin Matuska "l2mru%": [6, 100, "L2ARC MRU percentage"], 150716fd348SMartin Matuska "l2data%": [7, 100, "L2ARC data percentage"], 151716fd348SMartin Matuska "l2meta%": [7, 100, "L2ARC metadata percentage"], 152716fd348SMartin Matuska "l2asize": [7, 1024, "Actual (compressed) size of the L2ARC"], 153716fd348SMartin Matuska "l2size": [6, 1024, "Size of the L2ARC"], 154716fd348SMartin Matuska "l2bytes": [7, 1024, "Bytes read per second from the L2ARC"], 155*7a7741afSMartin Matuska "l2wbytes": [8, 1024, "Bytes written per second to the L2ARC"], 156716fd348SMartin Matuska "grow": [4, 1000, "ARC grow disabled"], 15715f0b8c3SMartin Matuska "need": [5, 1024, "ARC reclaim need"], 15815f0b8c3SMartin Matuska "free": [5, 1024, "ARC free memory"], 159716fd348SMartin Matuska "avail": [5, 1024, "ARC available memory"], 160716fd348SMartin Matuska "waste": [5, 1024, "Wasted memory due to round up to pagesize"], 1610d4ad640SMartin Matuska "ztotal": [6, 1000, "zfetch total prefetcher calls per second"], 1620d4ad640SMartin Matuska "zhits": [5, 1000, "zfetch stream hits per second"], 1630d4ad640SMartin Matuska "zahead": [6, 1000, "zfetch hits ahead of streams per second"], 1640d4ad640SMartin Matuska "zpast": [5, 1000, "zfetch hits behind streams per second"], 1650d4ad640SMartin Matuska "zmisses": [7, 1000, "zfetch stream misses per second"], 1660d4ad640SMartin Matuska "zmax": [4, 1000, "zfetch limit reached per second"], 1670d4ad640SMartin Matuska "zfuture": [7, 1000, "zfetch stream future per second"], 1680d4ad640SMartin Matuska "zstride": [7, 1000, "zfetch stream strides per second"], 1690d4ad640SMartin Matuska "zissued": [7, 1000, "zfetch prefetches issued per second"], 1700d4ad640SMartin Matuska "zactive": [7, 1000, "zfetch prefetches active per second"], 171716fd348SMartin Matuska} 172716fd348SMartin Matuska 173*7a7741afSMartin Matuska# ARC structural breakdown from arc_summary 174*7a7741afSMartin Matuskastructfields = { 175*7a7741afSMartin Matuska "cmp": ["compressed", "Compressed"], 176*7a7741afSMartin Matuska "ovh": ["overhead", "Overhead"], 177*7a7741afSMartin Matuska "bon": ["bonus", "Bonus"], 178*7a7741afSMartin Matuska "dno": ["dnode", "Dnode"], 179*7a7741afSMartin Matuska "dbu": ["dbuf", "Dbuf"], 180*7a7741afSMartin Matuska "hdr": ["hdr", "Header"], 181*7a7741afSMartin Matuska "l2h": ["l2_hdr", "L2 header"], 182*7a7741afSMartin Matuska "abd": ["abd_chunk_waste", "ABD chunk waste"], 183*7a7741afSMartin Matuska} 184*7a7741afSMartin Matuskastructstats = { # size stats 185*7a7741afSMartin Matuska "percent": "size", # percentage of this value 186*7a7741afSMartin Matuska "sz": ["_size", "size"], 187*7a7741afSMartin Matuska} 188*7a7741afSMartin Matuska 189*7a7741afSMartin Matuska# ARC types breakdown from arc_summary 190*7a7741afSMartin Matuskatypefields = { 191*7a7741afSMartin Matuska "data": ["data", "ARC data"], 192*7a7741afSMartin Matuska "meta": ["metadata", "ARC metadata"], 193*7a7741afSMartin Matuska} 194*7a7741afSMartin Matuskatypestats = { # size stats 195*7a7741afSMartin Matuska "percent": "cachessz", # percentage of this value 196*7a7741afSMartin Matuska "tg": ["_target", "target"], 197*7a7741afSMartin Matuska "sz": ["_size", "size"], 198*7a7741afSMartin Matuska} 199*7a7741afSMartin Matuska 200*7a7741afSMartin Matuska# ARC states breakdown from arc_summary 201*7a7741afSMartin Matuskastatefields = { 202*7a7741afSMartin Matuska "ano": ["anon", "Anonymous"], 203*7a7741afSMartin Matuska "mfu": ["mfu", "MFU"], 204*7a7741afSMartin Matuska "mru": ["mru", "MRU"], 205*7a7741afSMartin Matuska "unc": ["uncached", "Uncached"], 206*7a7741afSMartin Matuska} 207*7a7741afSMartin Matuskatargetstats = { 208*7a7741afSMartin Matuska "percent": "cachessz", # percentage of this value 209*7a7741afSMartin Matuska "fields": ["mfu", "mru"], # only applicable to these fields 210*7a7741afSMartin Matuska "tg": ["_target", "target"], 211*7a7741afSMartin Matuska "dt": ["_data_target", "data target"], 212*7a7741afSMartin Matuska "mt": ["_metadata_target", "metadata target"], 213*7a7741afSMartin Matuska} 214*7a7741afSMartin Matuskastatestats = { # size stats 215*7a7741afSMartin Matuska "percent": "cachessz", # percentage of this value 216*7a7741afSMartin Matuska "sz": ["_size", "size"], 217*7a7741afSMartin Matuska "da": ["_data", "data size"], 218*7a7741afSMartin Matuska "me": ["_metadata", "metadata size"], 219*7a7741afSMartin Matuska "ed": ["_evictable_data", "evictable data size"], 220*7a7741afSMartin Matuska "em": ["_evictable_metadata", "evictable metadata size"], 221*7a7741afSMartin Matuska} 222*7a7741afSMartin Matuskaghoststats = { 223*7a7741afSMartin Matuska "fields": ["mfu", "mru"], # only applicable to these fields 224*7a7741afSMartin Matuska "gsz": ["_ghost_size", "ghost size"], 225*7a7741afSMartin Matuska "gd": ["_ghost_data", "ghost data size"], 226*7a7741afSMartin Matuska "gm": ["_ghost_metadata", "ghost metadata size"], 227*7a7741afSMartin Matuska} 228*7a7741afSMartin Matuska 229*7a7741afSMartin Matuska# fields and stats 230*7a7741afSMartin Matuskafieldstats = [ 231*7a7741afSMartin Matuska [structfields, structstats], 232*7a7741afSMartin Matuska [typefields, typestats], 233*7a7741afSMartin Matuska [statefields, targetstats, statestats, ghoststats], 234*7a7741afSMartin Matuska] 235*7a7741afSMartin Matuskafor fs in fieldstats: 236*7a7741afSMartin Matuska fields, stats = fs[0], fs[1:] 237*7a7741afSMartin Matuska for field, fieldval in fields.items(): 238*7a7741afSMartin Matuska for group in stats: 239*7a7741afSMartin Matuska for stat, statval in group.items(): 240*7a7741afSMartin Matuska if stat in ["fields", "percent"] or \ 241*7a7741afSMartin Matuska ("fields" in group and field not in group["fields"]): 242*7a7741afSMartin Matuska continue 243*7a7741afSMartin Matuska colname = field + stat 244*7a7741afSMartin Matuska coldesc = fieldval[1] + " " + statval[1] 245*7a7741afSMartin Matuska cols[colname] = [len(colname), 1024, coldesc] 246*7a7741afSMartin Matuska if "percent" in group: 247*7a7741afSMartin Matuska cols[colname + "%"] = [len(colname) + 1, 100, \ 248*7a7741afSMartin Matuska coldesc + " percentage"] 249*7a7741afSMartin Matuska 250716fd348SMartin Matuskav = {} 25115f0b8c3SMartin Matuskahdr = ["time", "read", "ddread", "ddh%", "dmread", "dmh%", "pread", "ph%", 25215f0b8c3SMartin Matuska "size", "c", "avail"] 25315f0b8c3SMartin Matuskaxhdr = ["time", "mfu", "mru", "mfug", "mrug", "unc", "eskip", "mtxmis", 25415f0b8c3SMartin Matuska "dread", "pread", "read"] 2550d4ad640SMartin Matuskazhdr = ["time", "ztotal", "zhits", "zahead", "zpast", "zmisses", "zmax", 2560d4ad640SMartin Matuska "zfuture", "zstride", "zissued", "zactive"] 257716fd348SMartin Matuskasint = 1 # Default interval is 1 second 258716fd348SMartin Matuskacount = 1 # Default count is 1 259716fd348SMartin Matuskahdr_intr = 20 # Print header every 20 lines of output 260716fd348SMartin Matuskaopfile = None 261716fd348SMartin Matuskasep = " " # Default separator is 2 spaces 262716fd348SMartin Matuskal2exist = False 263716fd348SMartin Matuskacmd = ("Usage: arcstat [-havxp] [-f fields] [-o file] [-s string] [interval " 264716fd348SMartin Matuska "[count]]\n") 265716fd348SMartin Matuskacur = {} 266716fd348SMartin Matuskad = {} 267716fd348SMartin Matuskaout = None 268716fd348SMartin Matuskakstat = None 269716fd348SMartin Matuskapretty_print = True 270716fd348SMartin Matuska 271716fd348SMartin Matuska 272716fd348SMartin Matuskaif sys.platform.startswith('freebsd'): 273716fd348SMartin Matuska # Requires py-sysctl on FreeBSD 274716fd348SMartin Matuska import sysctl 275716fd348SMartin Matuska 276716fd348SMartin Matuska def kstat_update(): 277716fd348SMartin Matuska global kstat 278716fd348SMartin Matuska 279716fd348SMartin Matuska k = [ctl for ctl in sysctl.filter('kstat.zfs.misc.arcstats') 280716fd348SMartin Matuska if ctl.type != sysctl.CTLTYPE_NODE] 281b985c9caSMartin Matuska k += [ctl for ctl in sysctl.filter('kstat.zfs.misc.zfetchstats') 282b985c9caSMartin Matuska if ctl.type != sysctl.CTLTYPE_NODE] 283716fd348SMartin Matuska 284716fd348SMartin Matuska if not k: 285716fd348SMartin Matuska sys.exit(1) 286716fd348SMartin Matuska 287716fd348SMartin Matuska kstat = {} 288716fd348SMartin Matuska 289716fd348SMartin Matuska for s in k: 290716fd348SMartin Matuska if not s: 291716fd348SMartin Matuska continue 292716fd348SMartin Matuska 293716fd348SMartin Matuska name, value = s.name, s.value 294b985c9caSMartin Matuska 295b985c9caSMartin Matuska if "arcstats" in name: 296716fd348SMartin Matuska # Trims 'kstat.zfs.misc.arcstats' from the name 297716fd348SMartin Matuska kstat[name[24:]] = int(value) 298b985c9caSMartin Matuska else: 299b985c9caSMartin Matuska kstat["zfetch_" + name[27:]] = int(value) 300716fd348SMartin Matuska 301716fd348SMartin Matuskaelif sys.platform.startswith('linux'): 302716fd348SMartin Matuska def kstat_update(): 303716fd348SMartin Matuska global kstat 304716fd348SMartin Matuska 3050d4ad640SMartin Matuska k1 = [line.strip() for line in open('/proc/spl/kstat/zfs/arcstats')] 306716fd348SMartin Matuska 3070d4ad640SMartin Matuska k2 = ["zfetch_" + line.strip() for line in 3080d4ad640SMartin Matuska open('/proc/spl/kstat/zfs/zfetchstats')] 3090d4ad640SMartin Matuska 3100d4ad640SMartin Matuska if k1 is None or k2 is None: 311716fd348SMartin Matuska sys.exit(1) 312716fd348SMartin Matuska 3130d4ad640SMartin Matuska del k1[0:2] 3140d4ad640SMartin Matuska del k2[0:2] 3150d4ad640SMartin Matuska k = k1 + k2 316716fd348SMartin Matuska kstat = {} 317716fd348SMartin Matuska 318716fd348SMartin Matuska for s in k: 319716fd348SMartin Matuska if not s: 320716fd348SMartin Matuska continue 321716fd348SMartin Matuska 322716fd348SMartin Matuska name, unused, value = s.split() 323716fd348SMartin Matuska kstat[name] = int(value) 324716fd348SMartin Matuska 325716fd348SMartin Matuska 326716fd348SMartin Matuskadef detailed_usage(): 327716fd348SMartin Matuska sys.stderr.write("%s\n" % cmd) 328716fd348SMartin Matuska sys.stderr.write("Field definitions are as follows:\n") 329716fd348SMartin Matuska for key in cols: 330716fd348SMartin Matuska sys.stderr.write("%11s : %s\n" % (key, cols[key][2])) 331716fd348SMartin Matuska sys.stderr.write("\n") 332716fd348SMartin Matuska 333716fd348SMartin Matuska sys.exit(0) 334716fd348SMartin Matuska 335716fd348SMartin Matuska 336716fd348SMartin Matuskadef usage(): 337716fd348SMartin Matuska sys.stderr.write("%s\n" % cmd) 338716fd348SMartin Matuska sys.stderr.write("\t -h : Print this help message\n") 339716fd348SMartin Matuska sys.stderr.write("\t -a : Print all possible stats\n") 340716fd348SMartin Matuska sys.stderr.write("\t -v : List all possible field headers and definitions" 341716fd348SMartin Matuska "\n") 342716fd348SMartin Matuska sys.stderr.write("\t -x : Print extended stats\n") 3430d4ad640SMartin Matuska sys.stderr.write("\t -z : Print zfetch stats\n") 344716fd348SMartin Matuska sys.stderr.write("\t -f : Specify specific fields to print (see -v)\n") 345716fd348SMartin Matuska sys.stderr.write("\t -o : Redirect output to the specified file\n") 346716fd348SMartin Matuska sys.stderr.write("\t -s : Override default field separator with custom " 347716fd348SMartin Matuska "character or string\n") 348716fd348SMartin Matuska sys.stderr.write("\t -p : Disable auto-scaling of numerical fields\n") 349716fd348SMartin Matuska sys.stderr.write("\nExamples:\n") 350716fd348SMartin Matuska sys.stderr.write("\tarcstat -o /tmp/a.log 2 10\n") 351716fd348SMartin Matuska sys.stderr.write("\tarcstat -s \",\" -o /tmp/a.log 2 10\n") 352716fd348SMartin Matuska sys.stderr.write("\tarcstat -v\n") 353716fd348SMartin Matuska sys.stderr.write("\tarcstat -f time,hit%,dh%,ph%,mh% 1\n") 354716fd348SMartin Matuska sys.stderr.write("\n") 355716fd348SMartin Matuska 356716fd348SMartin Matuska sys.exit(1) 357716fd348SMartin Matuska 358716fd348SMartin Matuska 359716fd348SMartin Matuskadef snap_stats(): 360716fd348SMartin Matuska global cur 361716fd348SMartin Matuska global kstat 362716fd348SMartin Matuska 363716fd348SMartin Matuska prev = copy.deepcopy(cur) 364716fd348SMartin Matuska kstat_update() 365716fd348SMartin Matuska 366716fd348SMartin Matuska cur = kstat 367*7a7741afSMartin Matuska 368*7a7741afSMartin Matuska # fill in additional values from arc_summary 369*7a7741afSMartin Matuska cur["caches_size"] = caches_size = cur["anon_data"]+cur["anon_metadata"]+\ 370*7a7741afSMartin Matuska cur["mfu_data"]+cur["mfu_metadata"]+cur["mru_data"]+cur["mru_metadata"]+\ 371*7a7741afSMartin Matuska cur["uncached_data"]+cur["uncached_metadata"] 372*7a7741afSMartin Matuska s = 4294967296 373*7a7741afSMartin Matuska pd = cur["pd"] 374*7a7741afSMartin Matuska pm = cur["pm"] 375*7a7741afSMartin Matuska meta = cur["meta"] 376*7a7741afSMartin Matuska v = (s-int(pd))*(s-int(meta))/s 377*7a7741afSMartin Matuska cur["mfu_data_target"] = v / 65536 * caches_size / 65536 378*7a7741afSMartin Matuska v = (s-int(pm))*int(meta)/s 379*7a7741afSMartin Matuska cur["mfu_metadata_target"] = v / 65536 * caches_size / 65536 380*7a7741afSMartin Matuska v = int(pd)*(s-int(meta))/s 381*7a7741afSMartin Matuska cur["mru_data_target"] = v / 65536 * caches_size / 65536 382*7a7741afSMartin Matuska v = int(pm)*int(meta)/s 383*7a7741afSMartin Matuska cur["mru_metadata_target"] = v / 65536 * caches_size / 65536 384*7a7741afSMartin Matuska 385*7a7741afSMartin Matuska cur["data_target"] = cur["mfu_data_target"] + cur["mru_data_target"] 386*7a7741afSMartin Matuska cur["metadata_target"] = cur["mfu_metadata_target"] + cur["mru_metadata_target"] 387*7a7741afSMartin Matuska cur["mfu_target"] = cur["mfu_data_target"] + cur["mfu_metadata_target"] 388*7a7741afSMartin Matuska cur["mru_target"] = cur["mru_data_target"] + cur["mru_metadata_target"] 389*7a7741afSMartin Matuska 390716fd348SMartin Matuska for key in cur: 391716fd348SMartin Matuska if re.match(key, "class"): 392716fd348SMartin Matuska continue 393716fd348SMartin Matuska if key in prev: 394716fd348SMartin Matuska d[key] = cur[key] - prev[key] 395716fd348SMartin Matuska else: 396716fd348SMartin Matuska d[key] = cur[key] 397716fd348SMartin Matuska 398716fd348SMartin Matuska 399*7a7741afSMartin Matuskadef isint(num): 400*7a7741afSMartin Matuska if isinstance(num, float): 401*7a7741afSMartin Matuska return num.is_integer() 402*7a7741afSMartin Matuska if isinstance(num, int): 403*7a7741afSMartin Matuska return True 404*7a7741afSMartin Matuska return False 405*7a7741afSMartin Matuska 406*7a7741afSMartin Matuska 407716fd348SMartin Matuskadef prettynum(sz, scale, num=0): 408716fd348SMartin Matuska suffix = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z'] 409716fd348SMartin Matuska index = 0 410716fd348SMartin Matuska 411716fd348SMartin Matuska # Special case for date field 412716fd348SMartin Matuska if scale == -1: 413716fd348SMartin Matuska return "%s" % num 414716fd348SMartin Matuska 415*7a7741afSMartin Matuska if scale != 100: 416716fd348SMartin Matuska while abs(num) > scale and index < 5: 417716fd348SMartin Matuska num = num / scale 418716fd348SMartin Matuska index += 1 419716fd348SMartin Matuska 420*7a7741afSMartin Matuska width = sz - (0 if index == 0 else 1) 421*7a7741afSMartin Matuska intlen = len("%.0f" % num) # %.0f rounds to nearest int 422*7a7741afSMartin Matuska if sint == 1 and isint(num) or width < intlen + 2: 423*7a7741afSMartin Matuska decimal = 0 424716fd348SMartin Matuska else: 425*7a7741afSMartin Matuska decimal = 1 426*7a7741afSMartin Matuska return "%*.*f%s" % (width, decimal, num, suffix[index]) 427716fd348SMartin Matuska 428716fd348SMartin Matuska 429716fd348SMartin Matuskadef print_values(): 430716fd348SMartin Matuska global hdr 431716fd348SMartin Matuska global sep 432716fd348SMartin Matuska global v 433716fd348SMartin Matuska global pretty_print 434716fd348SMartin Matuska 435716fd348SMartin Matuska if pretty_print: 436716fd348SMartin Matuska fmt = lambda col: prettynum(cols[col][0], cols[col][1], v[col]) 437716fd348SMartin Matuska else: 43808aba0aeSMartin Matuska fmt = lambda col: str(v[col]) 439716fd348SMartin Matuska 440716fd348SMartin Matuska sys.stdout.write(sep.join(fmt(col) for col in hdr)) 441716fd348SMartin Matuska sys.stdout.write("\n") 442716fd348SMartin Matuska sys.stdout.flush() 443716fd348SMartin Matuska 444716fd348SMartin Matuska 445716fd348SMartin Matuskadef print_header(): 446716fd348SMartin Matuska global hdr 447716fd348SMartin Matuska global sep 448716fd348SMartin Matuska global pretty_print 449716fd348SMartin Matuska 450716fd348SMartin Matuska if pretty_print: 451716fd348SMartin Matuska fmt = lambda col: "%*s" % (cols[col][0], col) 452716fd348SMartin Matuska else: 453716fd348SMartin Matuska fmt = lambda col: col 454716fd348SMartin Matuska 455716fd348SMartin Matuska sys.stdout.write(sep.join(fmt(col) for col in hdr)) 456716fd348SMartin Matuska sys.stdout.write("\n") 457716fd348SMartin Matuska 458716fd348SMartin Matuska 459716fd348SMartin Matuskadef get_terminal_lines(): 460716fd348SMartin Matuska try: 461716fd348SMartin Matuska import fcntl 462716fd348SMartin Matuska import termios 463716fd348SMartin Matuska import struct 464716fd348SMartin Matuska data = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, '1234') 465716fd348SMartin Matuska sz = struct.unpack('hh', data) 466716fd348SMartin Matuska return sz[0] 467716fd348SMartin Matuska except Exception: 468716fd348SMartin Matuska pass 469716fd348SMartin Matuska 470716fd348SMartin Matuska 471716fd348SMartin Matuskadef update_hdr_intr(): 472716fd348SMartin Matuska global hdr_intr 473716fd348SMartin Matuska 474716fd348SMartin Matuska lines = get_terminal_lines() 475716fd348SMartin Matuska if lines and lines > 3: 476716fd348SMartin Matuska hdr_intr = lines - 3 477716fd348SMartin Matuska 478716fd348SMartin Matuska 479716fd348SMartin Matuskadef resize_handler(signum, frame): 480716fd348SMartin Matuska update_hdr_intr() 481716fd348SMartin Matuska 482716fd348SMartin Matuska 483716fd348SMartin Matuskadef init(): 484716fd348SMartin Matuska global sint 485716fd348SMartin Matuska global count 486716fd348SMartin Matuska global hdr 487716fd348SMartin Matuska global xhdr 4880d4ad640SMartin Matuska global zhdr 489716fd348SMartin Matuska global opfile 490716fd348SMartin Matuska global sep 491716fd348SMartin Matuska global out 492716fd348SMartin Matuska global l2exist 493716fd348SMartin Matuska global pretty_print 494716fd348SMartin Matuska 495716fd348SMartin Matuska desired_cols = None 496716fd348SMartin Matuska aflag = False 497716fd348SMartin Matuska xflag = False 498716fd348SMartin Matuska hflag = False 499716fd348SMartin Matuska vflag = False 5000d4ad640SMartin Matuska zflag = False 501716fd348SMartin Matuska i = 1 502716fd348SMartin Matuska 503716fd348SMartin Matuska try: 504716fd348SMartin Matuska opts, args = getopt.getopt( 505716fd348SMartin Matuska sys.argv[1:], 5060d4ad640SMartin Matuska "axzo:hvs:f:p", 507716fd348SMartin Matuska [ 508716fd348SMartin Matuska "all", 509716fd348SMartin Matuska "extended", 5100d4ad640SMartin Matuska "zfetch", 511716fd348SMartin Matuska "outfile", 512716fd348SMartin Matuska "help", 513716fd348SMartin Matuska "verbose", 514716fd348SMartin Matuska "separator", 515716fd348SMartin Matuska "columns", 516716fd348SMartin Matuska "parsable" 517716fd348SMartin Matuska ] 518716fd348SMartin Matuska ) 519716fd348SMartin Matuska except getopt.error as msg: 520716fd348SMartin Matuska sys.stderr.write("Error: %s\n" % str(msg)) 521716fd348SMartin Matuska usage() 522716fd348SMartin Matuska opts = None 523716fd348SMartin Matuska 524716fd348SMartin Matuska for opt, arg in opts: 525716fd348SMartin Matuska if opt in ('-a', '--all'): 526716fd348SMartin Matuska aflag = True 527716fd348SMartin Matuska if opt in ('-x', '--extended'): 528716fd348SMartin Matuska xflag = True 529716fd348SMartin Matuska if opt in ('-o', '--outfile'): 530716fd348SMartin Matuska opfile = arg 531716fd348SMartin Matuska i += 1 532716fd348SMartin Matuska if opt in ('-h', '--help'): 533716fd348SMartin Matuska hflag = True 534716fd348SMartin Matuska if opt in ('-v', '--verbose'): 535716fd348SMartin Matuska vflag = True 536716fd348SMartin Matuska if opt in ('-s', '--separator'): 537716fd348SMartin Matuska sep = arg 538716fd348SMartin Matuska i += 1 539716fd348SMartin Matuska if opt in ('-f', '--columns'): 540716fd348SMartin Matuska desired_cols = arg 541716fd348SMartin Matuska i += 1 542716fd348SMartin Matuska if opt in ('-p', '--parsable'): 543716fd348SMartin Matuska pretty_print = False 5440d4ad640SMartin Matuska if opt in ('-z', '--zfetch'): 5450d4ad640SMartin Matuska zflag = True 546716fd348SMartin Matuska i += 1 547716fd348SMartin Matuska 548716fd348SMartin Matuska argv = sys.argv[i:] 549716fd348SMartin Matuska sint = int(argv[0]) if argv else sint 550716fd348SMartin Matuska count = int(argv[1]) if len(argv) > 1 else (0 if len(argv) > 0 else 1) 551716fd348SMartin Matuska 5520d4ad640SMartin Matuska if hflag or (xflag and zflag) or ((zflag or xflag) and desired_cols): 553716fd348SMartin Matuska usage() 554716fd348SMartin Matuska 555716fd348SMartin Matuska if vflag: 556716fd348SMartin Matuska detailed_usage() 557716fd348SMartin Matuska 558716fd348SMartin Matuska if xflag: 559716fd348SMartin Matuska hdr = xhdr 560716fd348SMartin Matuska 5610d4ad640SMartin Matuska if zflag: 5620d4ad640SMartin Matuska hdr = zhdr 5630d4ad640SMartin Matuska 564716fd348SMartin Matuska update_hdr_intr() 565716fd348SMartin Matuska 566716fd348SMartin Matuska # check if L2ARC exists 567716fd348SMartin Matuska snap_stats() 568716fd348SMartin Matuska l2_size = cur.get("l2_size") 569716fd348SMartin Matuska if l2_size: 570716fd348SMartin Matuska l2exist = True 571716fd348SMartin Matuska 572716fd348SMartin Matuska if desired_cols: 573716fd348SMartin Matuska hdr = desired_cols.split(",") 574716fd348SMartin Matuska 575716fd348SMartin Matuska invalid = [] 576716fd348SMartin Matuska incompat = [] 577716fd348SMartin Matuska for ele in hdr: 578716fd348SMartin Matuska if ele not in cols: 579716fd348SMartin Matuska invalid.append(ele) 580716fd348SMartin Matuska elif not l2exist and ele.startswith("l2"): 581716fd348SMartin Matuska sys.stdout.write("No L2ARC Here\n%s\n" % ele) 582716fd348SMartin Matuska incompat.append(ele) 583716fd348SMartin Matuska 584716fd348SMartin Matuska if len(invalid) > 0: 585716fd348SMartin Matuska sys.stderr.write("Invalid column definition! -- %s\n" % invalid) 586716fd348SMartin Matuska usage() 587716fd348SMartin Matuska 588716fd348SMartin Matuska if len(incompat) > 0: 589716fd348SMartin Matuska sys.stderr.write("Incompatible field specified! -- %s\n" % 590716fd348SMartin Matuska incompat) 591716fd348SMartin Matuska usage() 592716fd348SMartin Matuska 593716fd348SMartin Matuska if aflag: 594716fd348SMartin Matuska if l2exist: 595716fd348SMartin Matuska hdr = cols.keys() 596716fd348SMartin Matuska else: 597716fd348SMartin Matuska hdr = [col for col in cols.keys() if not col.startswith("l2")] 598716fd348SMartin Matuska 599716fd348SMartin Matuska if opfile: 600716fd348SMartin Matuska try: 601716fd348SMartin Matuska out = open(opfile, "w") 602716fd348SMartin Matuska sys.stdout = out 603716fd348SMartin Matuska 604716fd348SMartin Matuska except IOError: 605716fd348SMartin Matuska sys.stderr.write("Cannot open %s for writing\n" % opfile) 606716fd348SMartin Matuska sys.exit(1) 607716fd348SMartin Matuska 608716fd348SMartin Matuska 609716fd348SMartin Matuskadef calculate(): 610716fd348SMartin Matuska global d 611716fd348SMartin Matuska global v 612716fd348SMartin Matuska global l2exist 613716fd348SMartin Matuska 614716fd348SMartin Matuska v = dict() 615716fd348SMartin Matuska v["time"] = time.strftime("%H:%M:%S", time.localtime()) 616*7a7741afSMartin Matuska v["hits"] = d["hits"] / sint 617*7a7741afSMartin Matuska v["iohs"] = d["iohits"] / sint 618*7a7741afSMartin Matuska v["miss"] = d["misses"] / sint 61915f0b8c3SMartin Matuska v["read"] = v["hits"] + v["iohs"] + v["miss"] 620*7a7741afSMartin Matuska v["hit%"] = 100 * v["hits"] / v["read"] if v["read"] > 0 else 0 621*7a7741afSMartin Matuska v["ioh%"] = 100 * v["iohs"] / v["read"] if v["read"] > 0 else 0 62215f0b8c3SMartin Matuska v["miss%"] = 100 - v["hit%"] - v["ioh%"] if v["read"] > 0 else 0 623716fd348SMartin Matuska 624*7a7741afSMartin Matuska v["dhit"] = (d["demand_data_hits"] + d["demand_metadata_hits"]) / sint 625*7a7741afSMartin Matuska v["dioh"] = (d["demand_data_iohits"] + d["demand_metadata_iohits"]) / sint 626*7a7741afSMartin Matuska v["dmis"] = (d["demand_data_misses"] + d["demand_metadata_misses"]) / sint 627716fd348SMartin Matuska 62815f0b8c3SMartin Matuska v["dread"] = v["dhit"] + v["dioh"] + v["dmis"] 629*7a7741afSMartin Matuska v["dh%"] = 100 * v["dhit"] / v["dread"] if v["dread"] > 0 else 0 630*7a7741afSMartin Matuska v["di%"] = 100 * v["dioh"] / v["dread"] if v["dread"] > 0 else 0 63115f0b8c3SMartin Matuska v["dm%"] = 100 - v["dh%"] - v["di%"] if v["dread"] > 0 else 0 63215f0b8c3SMartin Matuska 633*7a7741afSMartin Matuska v["ddhit"] = d["demand_data_hits"] / sint 634*7a7741afSMartin Matuska v["ddioh"] = d["demand_data_iohits"] / sint 635*7a7741afSMartin Matuska v["ddmis"] = d["demand_data_misses"] / sint 63615f0b8c3SMartin Matuska 63715f0b8c3SMartin Matuska v["ddread"] = v["ddhit"] + v["ddioh"] + v["ddmis"] 638*7a7741afSMartin Matuska v["ddh%"] = 100 * v["ddhit"] / v["ddread"] if v["ddread"] > 0 else 0 639*7a7741afSMartin Matuska v["ddi%"] = 100 * v["ddioh"] / v["ddread"] if v["ddread"] > 0 else 0 64015f0b8c3SMartin Matuska v["ddm%"] = 100 - v["ddh%"] - v["ddi%"] if v["ddread"] > 0 else 0 64115f0b8c3SMartin Matuska 642*7a7741afSMartin Matuska v["dmhit"] = d["demand_metadata_hits"] / sint 643*7a7741afSMartin Matuska v["dmioh"] = d["demand_metadata_iohits"] / sint 644*7a7741afSMartin Matuska v["dmmis"] = d["demand_metadata_misses"] / sint 64515f0b8c3SMartin Matuska 64615f0b8c3SMartin Matuska v["dmread"] = v["dmhit"] + v["dmioh"] + v["dmmis"] 647*7a7741afSMartin Matuska v["dmh%"] = 100 * v["dmhit"] / v["dmread"] if v["dmread"] > 0 else 0 648*7a7741afSMartin Matuska v["dmi%"] = 100 * v["dmioh"] / v["dmread"] if v["dmread"] > 0 else 0 64915f0b8c3SMartin Matuska v["dmm%"] = 100 - v["dmh%"] - v["dmi%"] if v["dmread"] > 0 else 0 650716fd348SMartin Matuska 651*7a7741afSMartin Matuska v["phit"] = (d["prefetch_data_hits"] + d["prefetch_metadata_hits"]) / sint 65215f0b8c3SMartin Matuska v["pioh"] = (d["prefetch_data_iohits"] + 653*7a7741afSMartin Matuska d["prefetch_metadata_iohits"]) / sint 654716fd348SMartin Matuska v["pmis"] = (d["prefetch_data_misses"] + 655*7a7741afSMartin Matuska d["prefetch_metadata_misses"]) / sint 656716fd348SMartin Matuska 65715f0b8c3SMartin Matuska v["pread"] = v["phit"] + v["pioh"] + v["pmis"] 658*7a7741afSMartin Matuska v["ph%"] = 100 * v["phit"] / v["pread"] if v["pread"] > 0 else 0 659*7a7741afSMartin Matuska v["pi%"] = 100 * v["pioh"] / v["pread"] if v["pread"] > 0 else 0 66015f0b8c3SMartin Matuska v["pm%"] = 100 - v["ph%"] - v["pi%"] if v["pread"] > 0 else 0 66115f0b8c3SMartin Matuska 662*7a7741afSMartin Matuska v["pdhit"] = d["prefetch_data_hits"] / sint 663*7a7741afSMartin Matuska v["pdioh"] = d["prefetch_data_iohits"] / sint 664*7a7741afSMartin Matuska v["pdmis"] = d["prefetch_data_misses"] / sint 66515f0b8c3SMartin Matuska 66615f0b8c3SMartin Matuska v["pdread"] = v["pdhit"] + v["pdioh"] + v["pdmis"] 667*7a7741afSMartin Matuska v["pdh%"] = 100 * v["pdhit"] / v["pdread"] if v["pdread"] > 0 else 0 668*7a7741afSMartin Matuska v["pdi%"] = 100 * v["pdioh"] / v["pdread"] if v["pdread"] > 0 else 0 66915f0b8c3SMartin Matuska v["pdm%"] = 100 - v["pdh%"] - v["pdi%"] if v["pdread"] > 0 else 0 67015f0b8c3SMartin Matuska 671*7a7741afSMartin Matuska v["pmhit"] = d["prefetch_metadata_hits"] / sint 672*7a7741afSMartin Matuska v["pmioh"] = d["prefetch_metadata_iohits"] / sint 673*7a7741afSMartin Matuska v["pmmis"] = d["prefetch_metadata_misses"] / sint 67415f0b8c3SMartin Matuska 67515f0b8c3SMartin Matuska v["pmread"] = v["pmhit"] + v["pmioh"] + v["pmmis"] 676*7a7741afSMartin Matuska v["pmh%"] = 100 * v["pmhit"] / v["pmread"] if v["pmread"] > 0 else 0 677*7a7741afSMartin Matuska v["pmi%"] = 100 * v["pmioh"] / v["pmread"] if v["pmread"] > 0 else 0 67815f0b8c3SMartin Matuska v["pmm%"] = 100 - v["pmh%"] - v["pmi%"] if v["pmread"] > 0 else 0 679716fd348SMartin Matuska 680716fd348SMartin Matuska v["mhit"] = (d["prefetch_metadata_hits"] + 681*7a7741afSMartin Matuska d["demand_metadata_hits"]) / sint 68215f0b8c3SMartin Matuska v["mioh"] = (d["prefetch_metadata_iohits"] + 683*7a7741afSMartin Matuska d["demand_metadata_iohits"]) / sint 684716fd348SMartin Matuska v["mmis"] = (d["prefetch_metadata_misses"] + 685*7a7741afSMartin Matuska d["demand_metadata_misses"]) / sint 686716fd348SMartin Matuska 68715f0b8c3SMartin Matuska v["mread"] = v["mhit"] + v["mioh"] + v["mmis"] 688*7a7741afSMartin Matuska v["mh%"] = 100 * v["mhit"] / v["mread"] if v["mread"] > 0 else 0 689*7a7741afSMartin Matuska v["mi%"] = 100 * v["mioh"] / v["mread"] if v["mread"] > 0 else 0 69015f0b8c3SMartin Matuska v["mm%"] = 100 - v["mh%"] - v["mi%"] if v["mread"] > 0 else 0 691716fd348SMartin Matuska 692716fd348SMartin Matuska v["arcsz"] = cur["size"] 693716fd348SMartin Matuska v["size"] = cur["size"] 694716fd348SMartin Matuska v["c"] = cur["c"] 695*7a7741afSMartin Matuska v["mfu"] = d["mfu_hits"] / sint 696*7a7741afSMartin Matuska v["mru"] = d["mru_hits"] / sint 697*7a7741afSMartin Matuska v["mrug"] = d["mru_ghost_hits"] / sint 698*7a7741afSMartin Matuska v["mfug"] = d["mfu_ghost_hits"] / sint 699*7a7741afSMartin Matuska v["unc"] = d["uncached_hits"] / sint 700*7a7741afSMartin Matuska v["eskip"] = d["evict_skip"] / sint 701*7a7741afSMartin Matuska v["el2skip"] = d["evict_l2_skip"] / sint 702*7a7741afSMartin Matuska v["el2cach"] = d["evict_l2_cached"] / sint 703*7a7741afSMartin Matuska v["el2el"] = d["evict_l2_eligible"] / sint 704*7a7741afSMartin Matuska v["el2mfu"] = d["evict_l2_eligible_mfu"] / sint 705*7a7741afSMartin Matuska v["el2mru"] = d["evict_l2_eligible_mru"] / sint 706*7a7741afSMartin Matuska v["el2inel"] = d["evict_l2_ineligible"] / sint 707*7a7741afSMartin Matuska v["mtxmis"] = d["mutex_miss"] / sint 7080d4ad640SMartin Matuska v["ztotal"] = (d["zfetch_hits"] + d["zfetch_future"] + d["zfetch_stride"] + 709*7a7741afSMartin Matuska d["zfetch_past"] + d["zfetch_misses"]) / sint 710*7a7741afSMartin Matuska v["zhits"] = d["zfetch_hits"] / sint 711*7a7741afSMartin Matuska v["zahead"] = (d["zfetch_future"] + d["zfetch_stride"]) / sint 712*7a7741afSMartin Matuska v["zpast"] = d["zfetch_past"] / sint 713*7a7741afSMartin Matuska v["zmisses"] = d["zfetch_misses"] / sint 714*7a7741afSMartin Matuska v["zmax"] = d["zfetch_max_streams"] / sint 715*7a7741afSMartin Matuska v["zfuture"] = d["zfetch_future"] / sint 716*7a7741afSMartin Matuska v["zstride"] = d["zfetch_stride"] / sint 717*7a7741afSMartin Matuska v["zissued"] = d["zfetch_io_issued"] / sint 718*7a7741afSMartin Matuska v["zactive"] = d["zfetch_io_active"] / sint 719*7a7741afSMartin Matuska 720*7a7741afSMartin Matuska # ARC structural breakdown, ARC types breakdown, ARC states breakdown 721*7a7741afSMartin Matuska v["cachessz"] = cur["caches_size"] 722*7a7741afSMartin Matuska for fs in fieldstats: 723*7a7741afSMartin Matuska fields, stats = fs[0], fs[1:] 724*7a7741afSMartin Matuska for field, fieldval in fields.items(): 725*7a7741afSMartin Matuska for group in stats: 726*7a7741afSMartin Matuska for stat, statval in group.items(): 727*7a7741afSMartin Matuska if stat in ["fields", "percent"] or \ 728*7a7741afSMartin Matuska ("fields" in group and field not in group["fields"]): 729*7a7741afSMartin Matuska continue 730*7a7741afSMartin Matuska colname = field + stat 731*7a7741afSMartin Matuska v[colname] = cur[fieldval[0] + statval[0]] 732*7a7741afSMartin Matuska if "percent" in group: 733*7a7741afSMartin Matuska v[colname + "%"] = 100 * v[colname] / \ 734*7a7741afSMartin Matuska v[group["percent"]] if v[group["percent"]] > 0 else 0 735716fd348SMartin Matuska 736716fd348SMartin Matuska if l2exist: 737*7a7741afSMartin Matuska v["l2hits"] = d["l2_hits"] / sint 738*7a7741afSMartin Matuska v["l2miss"] = d["l2_misses"] / sint 739716fd348SMartin Matuska v["l2read"] = v["l2hits"] + v["l2miss"] 740*7a7741afSMartin Matuska v["l2hit%"] = 100 * v["l2hits"] / v["l2read"] if v["l2read"] > 0 else 0 741716fd348SMartin Matuska 742716fd348SMartin Matuska v["l2miss%"] = 100 - v["l2hit%"] if v["l2read"] > 0 else 0 743716fd348SMartin Matuska v["l2asize"] = cur["l2_asize"] 744716fd348SMartin Matuska v["l2size"] = cur["l2_size"] 745*7a7741afSMartin Matuska v["l2bytes"] = d["l2_read_bytes"] / sint 746*7a7741afSMartin Matuska v["l2wbytes"] = d["l2_write_bytes"] / sint 747716fd348SMartin Matuska 748716fd348SMartin Matuska v["l2pref"] = cur["l2_prefetch_asize"] 749716fd348SMartin Matuska v["l2mfu"] = cur["l2_mfu_asize"] 750716fd348SMartin Matuska v["l2mru"] = cur["l2_mru_asize"] 751716fd348SMartin Matuska v["l2data"] = cur["l2_bufc_data_asize"] 752716fd348SMartin Matuska v["l2meta"] = cur["l2_bufc_metadata_asize"] 753*7a7741afSMartin Matuska v["l2pref%"] = 100 * v["l2pref"] / v["l2asize"] 754*7a7741afSMartin Matuska v["l2mfu%"] = 100 * v["l2mfu"] / v["l2asize"] 755*7a7741afSMartin Matuska v["l2mru%"] = 100 * v["l2mru"] / v["l2asize"] 756*7a7741afSMartin Matuska v["l2data%"] = 100 * v["l2data"] / v["l2asize"] 757*7a7741afSMartin Matuska v["l2meta%"] = 100 * v["l2meta"] / v["l2asize"] 758716fd348SMartin Matuska 759716fd348SMartin Matuska v["grow"] = 0 if cur["arc_no_grow"] else 1 760716fd348SMartin Matuska v["need"] = cur["arc_need_free"] 761716fd348SMartin Matuska v["free"] = cur["memory_free_bytes"] 762716fd348SMartin Matuska v["avail"] = cur["memory_available_bytes"] 763716fd348SMartin Matuska v["waste"] = cur["abd_chunk_waste_size"] 764716fd348SMartin Matuska 765716fd348SMartin Matuska 766716fd348SMartin Matuskadef main(): 767716fd348SMartin Matuska global sint 768716fd348SMartin Matuska global count 769716fd348SMartin Matuska global hdr_intr 770716fd348SMartin Matuska 771716fd348SMartin Matuska i = 0 772716fd348SMartin Matuska count_flag = 0 773716fd348SMartin Matuska 774716fd348SMartin Matuska init() 775716fd348SMartin Matuska if count > 0: 776716fd348SMartin Matuska count_flag = 1 777716fd348SMartin Matuska 778716fd348SMartin Matuska signal(SIGINT, SIG_DFL) 779716fd348SMartin Matuska signal(SIGWINCH, resize_handler) 780716fd348SMartin Matuska while True: 781716fd348SMartin Matuska if i == 0: 782716fd348SMartin Matuska print_header() 783716fd348SMartin Matuska 784716fd348SMartin Matuska snap_stats() 785716fd348SMartin Matuska calculate() 786716fd348SMartin Matuska print_values() 787716fd348SMartin Matuska 788716fd348SMartin Matuska if count_flag == 1: 789716fd348SMartin Matuska if count <= 1: 790716fd348SMartin Matuska break 791716fd348SMartin Matuska count -= 1 792716fd348SMartin Matuska 793716fd348SMartin Matuska i = 0 if i >= hdr_intr else i + 1 794716fd348SMartin Matuska time.sleep(sint) 795716fd348SMartin Matuska 796716fd348SMartin Matuska if out: 797716fd348SMartin Matuska out.close() 798716fd348SMartin Matuska 799716fd348SMartin Matuska 800716fd348SMartin Matuskaif __name__ == '__main__': 801716fd348SMartin Matuska main() 802