1*dd32d6b2SMartin Matuska#!/usr/bin/env @PYTHON_SHEBANG@ 2*dd32d6b2SMartin Matuska# SPDX-License-Identifier: CDDL-1.0 3*dd32d6b2SMartin Matuska# 4*dd32d6b2SMartin Matuska# Print out ZFS ARC Statistics exported via kstat(1) 5*dd32d6b2SMartin Matuska# For a definition of fields, or usage, use zarcstat -v 6*dd32d6b2SMartin Matuska# 7*dd32d6b2SMartin Matuska# This script was originally a fork of the original arcstat.pl (0.1) 8*dd32d6b2SMartin Matuska# by Neelakanth Nadgir, originally published on his Sun blog on 9*dd32d6b2SMartin Matuska# 09/18/2007 10*dd32d6b2SMartin Matuska# http://blogs.sun.com/realneel/entry/zfs_arc_statistics 11*dd32d6b2SMartin Matuska# 12*dd32d6b2SMartin Matuska# A new version aimed to improve upon the original by adding features 13*dd32d6b2SMartin Matuska# and fixing bugs as needed. This version was maintained by Mike 14*dd32d6b2SMartin Matuska# Harsch and was hosted in a public open source repository: 15*dd32d6b2SMartin Matuska# http://github.com/mharsch/arcstat 16*dd32d6b2SMartin Matuska# 17*dd32d6b2SMartin Matuska# but has since moved to the illumos-gate repository. 18*dd32d6b2SMartin Matuska# 19*dd32d6b2SMartin Matuska# This Python port was written by John Hixson for FreeNAS, introduced 20*dd32d6b2SMartin Matuska# in commit e2c29f: 21*dd32d6b2SMartin Matuska# https://github.com/freenas/freenas 22*dd32d6b2SMartin Matuska# 23*dd32d6b2SMartin Matuska# and has been improved by many people since. 24*dd32d6b2SMartin Matuska# 25*dd32d6b2SMartin Matuska# CDDL HEADER START 26*dd32d6b2SMartin Matuska# 27*dd32d6b2SMartin Matuska# The contents of this file are subject to the terms of the 28*dd32d6b2SMartin Matuska# Common Development and Distribution License, Version 1.0 only 29*dd32d6b2SMartin Matuska# (the "License"). You may not use this file except in compliance 30*dd32d6b2SMartin Matuska# with the License. 31*dd32d6b2SMartin Matuska# 32*dd32d6b2SMartin Matuska# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 33*dd32d6b2SMartin Matuska# or https://opensource.org/licenses/CDDL-1.0. 34*dd32d6b2SMartin Matuska# See the License for the specific language governing permissions 35*dd32d6b2SMartin Matuska# and limitations under the License. 36*dd32d6b2SMartin Matuska# 37*dd32d6b2SMartin Matuska# When distributing Covered Code, include this CDDL HEADER in each 38*dd32d6b2SMartin Matuska# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 39*dd32d6b2SMartin Matuska# If applicable, add the following below this CDDL HEADER, with the 40*dd32d6b2SMartin Matuska# fields enclosed by brackets "[]" replaced with your own identifying 41*dd32d6b2SMartin Matuska# information: Portions Copyright [yyyy] [name of copyright owner] 42*dd32d6b2SMartin Matuska# 43*dd32d6b2SMartin Matuska# CDDL HEADER END 44*dd32d6b2SMartin Matuska# 45*dd32d6b2SMartin Matuska# 46*dd32d6b2SMartin Matuska# Fields have a fixed width. Every interval, we fill the "v" 47*dd32d6b2SMartin Matuska# hash with its corresponding value (v[field]=value) using calculate(). 48*dd32d6b2SMartin Matuska# @hdr is the array of fields that needs to be printed, so we 49*dd32d6b2SMartin Matuska# just iterate over this array and print the values using our pretty printer. 50*dd32d6b2SMartin Matuska# 51*dd32d6b2SMartin Matuska# This script must remain compatible with Python 3.6+. 52*dd32d6b2SMartin Matuska# 53*dd32d6b2SMartin Matuska 54*dd32d6b2SMartin Matuskaimport sys 55*dd32d6b2SMartin Matuskaimport time 56*dd32d6b2SMartin Matuskaimport getopt 57*dd32d6b2SMartin Matuskaimport re 58*dd32d6b2SMartin Matuskaimport copy 59*dd32d6b2SMartin Matuskaimport os 60*dd32d6b2SMartin Matuska 61*dd32d6b2SMartin Matuskafrom signal import signal, SIGINT, SIGWINCH, SIG_DFL 62*dd32d6b2SMartin Matuska 63*dd32d6b2SMartin Matuska 64*dd32d6b2SMartin Matuskacols = { 65*dd32d6b2SMartin Matuska # HDR: [Size, Scale, Description] 66*dd32d6b2SMartin Matuska "time": [8, -1, "Time"], 67*dd32d6b2SMartin Matuska "hits": [4, 1000, "ARC hits per second"], 68*dd32d6b2SMartin Matuska "iohs": [4, 1000, "ARC I/O hits per second"], 69*dd32d6b2SMartin Matuska "miss": [4, 1000, "ARC misses per second"], 70*dd32d6b2SMartin Matuska "read": [4, 1000, "Total ARC accesses per second"], 71*dd32d6b2SMartin Matuska "hit%": [4, 100, "ARC hit percentage"], 72*dd32d6b2SMartin Matuska "ioh%": [4, 100, "ARC I/O hit percentage"], 73*dd32d6b2SMartin Matuska "miss%": [5, 100, "ARC miss percentage"], 74*dd32d6b2SMartin Matuska "dhit": [4, 1000, "Demand hits per second"], 75*dd32d6b2SMartin Matuska "dioh": [4, 1000, "Demand I/O hits per second"], 76*dd32d6b2SMartin Matuska "dmis": [4, 1000, "Demand misses per second"], 77*dd32d6b2SMartin Matuska "dh%": [3, 100, "Demand hit percentage"], 78*dd32d6b2SMartin Matuska "di%": [3, 100, "Demand I/O hit percentage"], 79*dd32d6b2SMartin Matuska "dm%": [3, 100, "Demand miss percentage"], 80*dd32d6b2SMartin Matuska "ddhit": [5, 1000, "Demand data hits per second"], 81*dd32d6b2SMartin Matuska "ddioh": [5, 1000, "Demand data I/O hits per second"], 82*dd32d6b2SMartin Matuska "ddmis": [5, 1000, "Demand data misses per second"], 83*dd32d6b2SMartin Matuska "ddh%": [4, 100, "Demand data hit percentage"], 84*dd32d6b2SMartin Matuska "ddi%": [4, 100, "Demand data I/O hit percentage"], 85*dd32d6b2SMartin Matuska "ddm%": [4, 100, "Demand data miss percentage"], 86*dd32d6b2SMartin Matuska "dmhit": [5, 1000, "Demand metadata hits per second"], 87*dd32d6b2SMartin Matuska "dmioh": [5, 1000, "Demand metadata I/O hits per second"], 88*dd32d6b2SMartin Matuska "dmmis": [5, 1000, "Demand metadata misses per second"], 89*dd32d6b2SMartin Matuska "dmh%": [4, 100, "Demand metadata hit percentage"], 90*dd32d6b2SMartin Matuska "dmi%": [4, 100, "Demand metadata I/O hit percentage"], 91*dd32d6b2SMartin Matuska "dmm%": [4, 100, "Demand metadata miss percentage"], 92*dd32d6b2SMartin Matuska "phit": [4, 1000, "Prefetch hits per second"], 93*dd32d6b2SMartin Matuska "pioh": [4, 1000, "Prefetch I/O hits per second"], 94*dd32d6b2SMartin Matuska "pmis": [4, 1000, "Prefetch misses per second"], 95*dd32d6b2SMartin Matuska "ph%": [3, 100, "Prefetch hits percentage"], 96*dd32d6b2SMartin Matuska "pi%": [3, 100, "Prefetch I/O hits percentage"], 97*dd32d6b2SMartin Matuska "pm%": [3, 100, "Prefetch miss percentage"], 98*dd32d6b2SMartin Matuska "pdhit": [5, 1000, "Prefetch data hits per second"], 99*dd32d6b2SMartin Matuska "pdioh": [5, 1000, "Prefetch data I/O hits per second"], 100*dd32d6b2SMartin Matuska "pdmis": [5, 1000, "Prefetch data misses per second"], 101*dd32d6b2SMartin Matuska "pdh%": [4, 100, "Prefetch data hits percentage"], 102*dd32d6b2SMartin Matuska "pdi%": [4, 100, "Prefetch data I/O hits percentage"], 103*dd32d6b2SMartin Matuska "pdm%": [4, 100, "Prefetch data miss percentage"], 104*dd32d6b2SMartin Matuska "pmhit": [5, 1000, "Prefetch metadata hits per second"], 105*dd32d6b2SMartin Matuska "pmioh": [5, 1000, "Prefetch metadata I/O hits per second"], 106*dd32d6b2SMartin Matuska "pmmis": [5, 1000, "Prefetch metadata misses per second"], 107*dd32d6b2SMartin Matuska "pmh%": [4, 100, "Prefetch metadata hits percentage"], 108*dd32d6b2SMartin Matuska "pmi%": [4, 100, "Prefetch metadata I/O hits percentage"], 109*dd32d6b2SMartin Matuska "pmm%": [4, 100, "Prefetch metadata miss percentage"], 110*dd32d6b2SMartin Matuska "mhit": [4, 1000, "Metadata hits per second"], 111*dd32d6b2SMartin Matuska "mioh": [4, 1000, "Metadata I/O hits per second"], 112*dd32d6b2SMartin Matuska "mmis": [4, 1000, "Metadata misses per second"], 113*dd32d6b2SMartin Matuska "mread": [5, 1000, "Metadata accesses per second"], 114*dd32d6b2SMartin Matuska "mh%": [3, 100, "Metadata hit percentage"], 115*dd32d6b2SMartin Matuska "mi%": [3, 100, "Metadata I/O hit percentage"], 116*dd32d6b2SMartin Matuska "mm%": [3, 100, "Metadata miss percentage"], 117*dd32d6b2SMartin Matuska "arcsz": [5, 1024, "ARC size"], 118*dd32d6b2SMartin Matuska "size": [5, 1024, "ARC size"], 119*dd32d6b2SMartin Matuska "c": [5, 1024, "ARC target size"], 120*dd32d6b2SMartin Matuska "mfu": [4, 1000, "MFU list hits per second"], 121*dd32d6b2SMartin Matuska "mru": [4, 1000, "MRU list hits per second"], 122*dd32d6b2SMartin Matuska "mfug": [4, 1000, "MFU ghost list hits per second"], 123*dd32d6b2SMartin Matuska "mrug": [4, 1000, "MRU ghost list hits per second"], 124*dd32d6b2SMartin Matuska "unc": [4, 1000, "Uncached list hits per second"], 125*dd32d6b2SMartin Matuska "eskip": [5, 1000, "evict_skip per second"], 126*dd32d6b2SMartin Matuska "el2skip": [7, 1000, "evict skip, due to l2 writes, per second"], 127*dd32d6b2SMartin Matuska "el2cach": [7, 1024, "Size of L2 cached evictions per second"], 128*dd32d6b2SMartin Matuska "el2el": [5, 1024, "Size of L2 eligible evictions per second"], 129*dd32d6b2SMartin Matuska "el2mfu": [6, 1024, "Size of L2 eligible MFU evictions per second"], 130*dd32d6b2SMartin Matuska "el2mru": [6, 1024, "Size of L2 eligible MRU evictions per second"], 131*dd32d6b2SMartin Matuska "el2inel": [7, 1024, "Size of L2 ineligible evictions per second"], 132*dd32d6b2SMartin Matuska "mtxmis": [6, 1000, "mutex_miss per second"], 133*dd32d6b2SMartin Matuska "dread": [5, 1000, "Demand accesses per second"], 134*dd32d6b2SMartin Matuska "ddread": [6, 1000, "Demand data accesses per second"], 135*dd32d6b2SMartin Matuska "dmread": [6, 1000, "Demand metadata accesses per second"], 136*dd32d6b2SMartin Matuska "pread": [5, 1000, "Prefetch accesses per second"], 137*dd32d6b2SMartin Matuska "pdread": [6, 1000, "Prefetch data accesses per second"], 138*dd32d6b2SMartin Matuska "pmread": [6, 1000, "Prefetch metadata accesses per second"], 139*dd32d6b2SMartin Matuska "l2hits": [6, 1000, "L2ARC hits per second"], 140*dd32d6b2SMartin Matuska "l2miss": [6, 1000, "L2ARC misses per second"], 141*dd32d6b2SMartin Matuska "l2read": [6, 1000, "Total L2ARC accesses per second"], 142*dd32d6b2SMartin Matuska "l2hit%": [6, 100, "L2ARC access hit percentage"], 143*dd32d6b2SMartin Matuska "l2miss%": [7, 100, "L2ARC access miss percentage"], 144*dd32d6b2SMartin Matuska "l2pref": [6, 1024, "L2ARC prefetch allocated size"], 145*dd32d6b2SMartin Matuska "l2mfu": [5, 1024, "L2ARC MFU allocated size"], 146*dd32d6b2SMartin Matuska "l2mru": [5, 1024, "L2ARC MRU allocated size"], 147*dd32d6b2SMartin Matuska "l2data": [6, 1024, "L2ARC data allocated size"], 148*dd32d6b2SMartin Matuska "l2meta": [6, 1024, "L2ARC metadata allocated size"], 149*dd32d6b2SMartin Matuska "l2pref%": [7, 100, "L2ARC prefetch percentage"], 150*dd32d6b2SMartin Matuska "l2mfu%": [6, 100, "L2ARC MFU percentage"], 151*dd32d6b2SMartin Matuska "l2mru%": [6, 100, "L2ARC MRU percentage"], 152*dd32d6b2SMartin Matuska "l2data%": [7, 100, "L2ARC data percentage"], 153*dd32d6b2SMartin Matuska "l2meta%": [7, 100, "L2ARC metadata percentage"], 154*dd32d6b2SMartin Matuska "l2asize": [7, 1024, "Actual (compressed) size of the L2ARC"], 155*dd32d6b2SMartin Matuska "l2size": [6, 1024, "Size of the L2ARC"], 156*dd32d6b2SMartin Matuska "l2bytes": [7, 1024, "Bytes read per second from the L2ARC"], 157*dd32d6b2SMartin Matuska "l2wbytes": [8, 1024, "Bytes written per second to the L2ARC"], 158*dd32d6b2SMartin Matuska "grow": [4, 1000, "ARC grow disabled"], 159*dd32d6b2SMartin Matuska "need": [5, 1024, "ARC reclaim need"], 160*dd32d6b2SMartin Matuska "free": [5, 1024, "ARC free memory"], 161*dd32d6b2SMartin Matuska "avail": [5, 1024, "ARC available memory"], 162*dd32d6b2SMartin Matuska "waste": [5, 1024, "Wasted memory due to round up to pagesize"], 163*dd32d6b2SMartin Matuska "ztotal": [6, 1000, "zfetch total prefetcher calls per second"], 164*dd32d6b2SMartin Matuska "zhits": [5, 1000, "zfetch stream hits per second"], 165*dd32d6b2SMartin Matuska "zahead": [6, 1000, "zfetch hits ahead of streams per second"], 166*dd32d6b2SMartin Matuska "zpast": [5, 1000, "zfetch hits behind streams per second"], 167*dd32d6b2SMartin Matuska "zmisses": [7, 1000, "zfetch stream misses per second"], 168*dd32d6b2SMartin Matuska "zmax": [4, 1000, "zfetch limit reached per second"], 169*dd32d6b2SMartin Matuska "zfuture": [7, 1000, "zfetch stream future per second"], 170*dd32d6b2SMartin Matuska "zstride": [7, 1000, "zfetch stream strides per second"], 171*dd32d6b2SMartin Matuska "zissued": [7, 1000, "zfetch prefetches issued per second"], 172*dd32d6b2SMartin Matuska "zactive": [7, 1000, "zfetch prefetches active per second"], 173*dd32d6b2SMartin Matuska} 174*dd32d6b2SMartin Matuska 175*dd32d6b2SMartin Matuska# ARC structural breakdown from zarcsummary 176*dd32d6b2SMartin Matuskastructfields = { 177*dd32d6b2SMartin Matuska "cmp": ["compressed", "Compressed"], 178*dd32d6b2SMartin Matuska "ovh": ["overhead", "Overhead"], 179*dd32d6b2SMartin Matuska "bon": ["bonus", "Bonus"], 180*dd32d6b2SMartin Matuska "dno": ["dnode", "Dnode"], 181*dd32d6b2SMartin Matuska "dbu": ["dbuf", "Dbuf"], 182*dd32d6b2SMartin Matuska "hdr": ["hdr", "Header"], 183*dd32d6b2SMartin Matuska "l2h": ["l2_hdr", "L2 header"], 184*dd32d6b2SMartin Matuska "abd": ["abd_chunk_waste", "ABD chunk waste"], 185*dd32d6b2SMartin Matuska} 186*dd32d6b2SMartin Matuskastructstats = { # size stats 187*dd32d6b2SMartin Matuska "percent": "size", # percentage of this value 188*dd32d6b2SMartin Matuska "sz": ["_size", "size"], 189*dd32d6b2SMartin Matuska} 190*dd32d6b2SMartin Matuska 191*dd32d6b2SMartin Matuska# ARC types breakdown from zarcsummary 192*dd32d6b2SMartin Matuskatypefields = { 193*dd32d6b2SMartin Matuska "data": ["data", "ARC data"], 194*dd32d6b2SMartin Matuska "meta": ["metadata", "ARC metadata"], 195*dd32d6b2SMartin Matuska} 196*dd32d6b2SMartin Matuskatypestats = { # size stats 197*dd32d6b2SMartin Matuska "percent": "cachessz", # percentage of this value 198*dd32d6b2SMartin Matuska "tg": ["_target", "target"], 199*dd32d6b2SMartin Matuska "sz": ["_size", "size"], 200*dd32d6b2SMartin Matuska} 201*dd32d6b2SMartin Matuska 202*dd32d6b2SMartin Matuska# ARC states breakdown from zarcsummary 203*dd32d6b2SMartin Matuskastatefields = { 204*dd32d6b2SMartin Matuska "ano": ["anon", "Anonymous"], 205*dd32d6b2SMartin Matuska "mfu": ["mfu", "MFU"], 206*dd32d6b2SMartin Matuska "mru": ["mru", "MRU"], 207*dd32d6b2SMartin Matuska "unc": ["uncached", "Uncached"], 208*dd32d6b2SMartin Matuska} 209*dd32d6b2SMartin Matuskatargetstats = { 210*dd32d6b2SMartin Matuska "percent": "cachessz", # percentage of this value 211*dd32d6b2SMartin Matuska "fields": ["mfu", "mru"], # only applicable to these fields 212*dd32d6b2SMartin Matuska "tg": ["_target", "target"], 213*dd32d6b2SMartin Matuska "dt": ["_data_target", "data target"], 214*dd32d6b2SMartin Matuska "mt": ["_metadata_target", "metadata target"], 215*dd32d6b2SMartin Matuska} 216*dd32d6b2SMartin Matuskastatestats = { # size stats 217*dd32d6b2SMartin Matuska "percent": "cachessz", # percentage of this value 218*dd32d6b2SMartin Matuska "sz": ["_size", "size"], 219*dd32d6b2SMartin Matuska "da": ["_data", "data size"], 220*dd32d6b2SMartin Matuska "me": ["_metadata", "metadata size"], 221*dd32d6b2SMartin Matuska "ed": ["_evictable_data", "evictable data size"], 222*dd32d6b2SMartin Matuska "em": ["_evictable_metadata", "evictable metadata size"], 223*dd32d6b2SMartin Matuska} 224*dd32d6b2SMartin Matuskaghoststats = { 225*dd32d6b2SMartin Matuska "fields": ["mfu", "mru"], # only applicable to these fields 226*dd32d6b2SMartin Matuska "gsz": ["_ghost_size", "ghost size"], 227*dd32d6b2SMartin Matuska "gd": ["_ghost_data", "ghost data size"], 228*dd32d6b2SMartin Matuska "gm": ["_ghost_metadata", "ghost metadata size"], 229*dd32d6b2SMartin Matuska} 230*dd32d6b2SMartin Matuska 231*dd32d6b2SMartin Matuska# fields and stats 232*dd32d6b2SMartin Matuskafieldstats = [ 233*dd32d6b2SMartin Matuska [structfields, structstats], 234*dd32d6b2SMartin Matuska [typefields, typestats], 235*dd32d6b2SMartin Matuska [statefields, targetstats, statestats, ghoststats], 236*dd32d6b2SMartin Matuska] 237*dd32d6b2SMartin Matuskafor fs in fieldstats: 238*dd32d6b2SMartin Matuska fields, stats = fs[0], fs[1:] 239*dd32d6b2SMartin Matuska for field, fieldval in fields.items(): 240*dd32d6b2SMartin Matuska for group in stats: 241*dd32d6b2SMartin Matuska for stat, statval in group.items(): 242*dd32d6b2SMartin Matuska if stat in ["fields", "percent"] or \ 243*dd32d6b2SMartin Matuska ("fields" in group and field not in group["fields"]): 244*dd32d6b2SMartin Matuska continue 245*dd32d6b2SMartin Matuska colname = field + stat 246*dd32d6b2SMartin Matuska coldesc = fieldval[1] + " " + statval[1] 247*dd32d6b2SMartin Matuska cols[colname] = [len(colname), 1024, coldesc] 248*dd32d6b2SMartin Matuska if "percent" in group: 249*dd32d6b2SMartin Matuska cols[colname + "%"] = [len(colname) + 1, 100, \ 250*dd32d6b2SMartin Matuska coldesc + " percentage"] 251*dd32d6b2SMartin Matuska 252*dd32d6b2SMartin Matuskav = {} 253*dd32d6b2SMartin Matuskahdr = ["time", "read", "ddread", "ddh%", "dmread", "dmh%", "pread", "ph%", 254*dd32d6b2SMartin Matuska "size", "c", "avail"] 255*dd32d6b2SMartin Matuskaxhdr = ["time", "mfu", "mru", "mfug", "mrug", "unc", "eskip", "mtxmis", 256*dd32d6b2SMartin Matuska "dread", "pread", "read"] 257*dd32d6b2SMartin Matuskazhdr = ["time", "ztotal", "zhits", "zahead", "zpast", "zmisses", "zmax", 258*dd32d6b2SMartin Matuska "zfuture", "zstride", "zissued", "zactive"] 259*dd32d6b2SMartin Matuskasint = 1 # Default interval is 1 second 260*dd32d6b2SMartin Matuskacount = 1 # Default count is 1 261*dd32d6b2SMartin Matuskahdr_intr = 20 # Print header every 20 lines of output 262*dd32d6b2SMartin Matuskaopfile = None 263*dd32d6b2SMartin Matuskasep = " " # Default separator is 2 spaces 264*dd32d6b2SMartin Matuskal2exist = False 265*dd32d6b2SMartin Matuskacmd = ("Usage: zarcstat [-havxp] [-f fields] [-o file] [-s string] [interval " 266*dd32d6b2SMartin Matuska "[count]]\n") 267*dd32d6b2SMartin Matuskacur = {} 268*dd32d6b2SMartin Matuskad = {} 269*dd32d6b2SMartin Matuskaout = None 270*dd32d6b2SMartin Matuskakstat = None 271*dd32d6b2SMartin Matuskapretty_print = True 272*dd32d6b2SMartin Matuska 273*dd32d6b2SMartin Matuska 274*dd32d6b2SMartin Matuskaif sys.platform.startswith('freebsd'): 275*dd32d6b2SMartin Matuska # Requires py-sysctl on FreeBSD 276*dd32d6b2SMartin Matuska import sysctl 277*dd32d6b2SMartin Matuska 278*dd32d6b2SMartin Matuska def kstat_update(): 279*dd32d6b2SMartin Matuska global kstat 280*dd32d6b2SMartin Matuska 281*dd32d6b2SMartin Matuska k = [ctl for ctl in sysctl.filter('kstat.zfs.misc.arcstats') 282*dd32d6b2SMartin Matuska if ctl.type != sysctl.CTLTYPE_NODE] 283*dd32d6b2SMartin Matuska k += [ctl for ctl in sysctl.filter('kstat.zfs.misc.zfetchstats') 284*dd32d6b2SMartin Matuska if ctl.type != sysctl.CTLTYPE_NODE] 285*dd32d6b2SMartin Matuska 286*dd32d6b2SMartin Matuska if not k: 287*dd32d6b2SMartin Matuska sys.exit(1) 288*dd32d6b2SMartin Matuska 289*dd32d6b2SMartin Matuska kstat = {} 290*dd32d6b2SMartin Matuska 291*dd32d6b2SMartin Matuska for s in k: 292*dd32d6b2SMartin Matuska if not s: 293*dd32d6b2SMartin Matuska continue 294*dd32d6b2SMartin Matuska 295*dd32d6b2SMartin Matuska name, value = s.name, s.value 296*dd32d6b2SMartin Matuska 297*dd32d6b2SMartin Matuska if "arcstats" in name: 298*dd32d6b2SMartin Matuska # Trims 'kstat.zfs.misc.arcstats' from the name 299*dd32d6b2SMartin Matuska kstat[name[24:]] = int(value) 300*dd32d6b2SMartin Matuska else: 301*dd32d6b2SMartin Matuska kstat["zfetch_" + name[27:]] = int(value) 302*dd32d6b2SMartin Matuska 303*dd32d6b2SMartin Matuskaelif sys.platform.startswith('linux'): 304*dd32d6b2SMartin Matuska def kstat_update(): 305*dd32d6b2SMartin Matuska global kstat 306*dd32d6b2SMartin Matuska 307*dd32d6b2SMartin Matuska k1 = [line.strip() for line in open('/proc/spl/kstat/zfs/arcstats')] 308*dd32d6b2SMartin Matuska 309*dd32d6b2SMartin Matuska k2 = ["zfetch_" + line.strip() for line in 310*dd32d6b2SMartin Matuska open('/proc/spl/kstat/zfs/zfetchstats')] 311*dd32d6b2SMartin Matuska 312*dd32d6b2SMartin Matuska if k1 is None or k2 is None: 313*dd32d6b2SMartin Matuska sys.exit(1) 314*dd32d6b2SMartin Matuska 315*dd32d6b2SMartin Matuska del k1[0:2] 316*dd32d6b2SMartin Matuska del k2[0:2] 317*dd32d6b2SMartin Matuska k = k1 + k2 318*dd32d6b2SMartin Matuska kstat = {} 319*dd32d6b2SMartin Matuska 320*dd32d6b2SMartin Matuska for s in k: 321*dd32d6b2SMartin Matuska if not s: 322*dd32d6b2SMartin Matuska continue 323*dd32d6b2SMartin Matuska 324*dd32d6b2SMartin Matuska name, unused, value = s.split() 325*dd32d6b2SMartin Matuska kstat[name] = int(value) 326*dd32d6b2SMartin Matuska 327*dd32d6b2SMartin Matuska 328*dd32d6b2SMartin Matuskadef detailed_usage(): 329*dd32d6b2SMartin Matuska sys.stderr.write("%s\n" % cmd) 330*dd32d6b2SMartin Matuska sys.stderr.write("Field definitions are as follows:\n") 331*dd32d6b2SMartin Matuska for key in cols: 332*dd32d6b2SMartin Matuska sys.stderr.write("%11s : %s\n" % (key, cols[key][2])) 333*dd32d6b2SMartin Matuska sys.stderr.write("\n") 334*dd32d6b2SMartin Matuska 335*dd32d6b2SMartin Matuska sys.exit(0) 336*dd32d6b2SMartin Matuska 337*dd32d6b2SMartin Matuska 338*dd32d6b2SMartin Matuskadef usage(): 339*dd32d6b2SMartin Matuska sys.stderr.write("%s\n" % cmd) 340*dd32d6b2SMartin Matuska sys.stderr.write("\t -h : Print this help message\n") 341*dd32d6b2SMartin Matuska sys.stderr.write("\t -a : Print all possible stats\n") 342*dd32d6b2SMartin Matuska sys.stderr.write("\t -v : List all possible field headers and definitions" 343*dd32d6b2SMartin Matuska "\n") 344*dd32d6b2SMartin Matuska sys.stderr.write("\t -x : Print extended stats\n") 345*dd32d6b2SMartin Matuska sys.stderr.write("\t -z : Print zfetch stats\n") 346*dd32d6b2SMartin Matuska sys.stderr.write("\t -f : Specify specific fields to print (see -v)\n") 347*dd32d6b2SMartin Matuska sys.stderr.write("\t -o : Redirect output to the specified file\n") 348*dd32d6b2SMartin Matuska sys.stderr.write("\t -s : Override default field separator with custom " 349*dd32d6b2SMartin Matuska "character or string\n") 350*dd32d6b2SMartin Matuska sys.stderr.write("\t -p : Disable auto-scaling of numerical fields\n") 351*dd32d6b2SMartin Matuska sys.stderr.write("\nExamples:\n") 352*dd32d6b2SMartin Matuska sys.stderr.write("\tzarcstat -o /tmp/a.log 2 10\n") 353*dd32d6b2SMartin Matuska sys.stderr.write("\tzarcstat -s \",\" -o /tmp/a.log 2 10\n") 354*dd32d6b2SMartin Matuska sys.stderr.write("\tzarcstat -v\n") 355*dd32d6b2SMartin Matuska sys.stderr.write("\tzarcstat -f time,hit%,dh%,ph%,mh% 1\n") 356*dd32d6b2SMartin Matuska sys.stderr.write("\n") 357*dd32d6b2SMartin Matuska 358*dd32d6b2SMartin Matuska sys.exit(1) 359*dd32d6b2SMartin Matuska 360*dd32d6b2SMartin Matuska 361*dd32d6b2SMartin Matuskadef snap_stats(): 362*dd32d6b2SMartin Matuska global cur 363*dd32d6b2SMartin Matuska global kstat 364*dd32d6b2SMartin Matuska 365*dd32d6b2SMartin Matuska prev = copy.deepcopy(cur) 366*dd32d6b2SMartin Matuska kstat_update() 367*dd32d6b2SMartin Matuska 368*dd32d6b2SMartin Matuska cur = kstat 369*dd32d6b2SMartin Matuska 370*dd32d6b2SMartin Matuska # fill in additional values from zarcsummary 371*dd32d6b2SMartin Matuska cur["caches_size"] = caches_size = cur["anon_data"]+cur["anon_metadata"]+\ 372*dd32d6b2SMartin Matuska cur["mfu_data"]+cur["mfu_metadata"]+cur["mru_data"]+cur["mru_metadata"]+\ 373*dd32d6b2SMartin Matuska cur["uncached_data"]+cur["uncached_metadata"] 374*dd32d6b2SMartin Matuska s = 4294967296 375*dd32d6b2SMartin Matuska pd = cur["pd"] 376*dd32d6b2SMartin Matuska pm = cur["pm"] 377*dd32d6b2SMartin Matuska meta = cur["meta"] 378*dd32d6b2SMartin Matuska v = (s-int(pd))*(s-int(meta))/s 379*dd32d6b2SMartin Matuska cur["mfu_data_target"] = v / 65536 * caches_size / 65536 380*dd32d6b2SMartin Matuska v = (s-int(pm))*int(meta)/s 381*dd32d6b2SMartin Matuska cur["mfu_metadata_target"] = v / 65536 * caches_size / 65536 382*dd32d6b2SMartin Matuska v = int(pd)*(s-int(meta))/s 383*dd32d6b2SMartin Matuska cur["mru_data_target"] = v / 65536 * caches_size / 65536 384*dd32d6b2SMartin Matuska v = int(pm)*int(meta)/s 385*dd32d6b2SMartin Matuska cur["mru_metadata_target"] = v / 65536 * caches_size / 65536 386*dd32d6b2SMartin Matuska 387*dd32d6b2SMartin Matuska cur["data_target"] = cur["mfu_data_target"] + cur["mru_data_target"] 388*dd32d6b2SMartin Matuska cur["metadata_target"] = cur["mfu_metadata_target"] + cur["mru_metadata_target"] 389*dd32d6b2SMartin Matuska cur["mfu_target"] = cur["mfu_data_target"] + cur["mfu_metadata_target"] 390*dd32d6b2SMartin Matuska cur["mru_target"] = cur["mru_data_target"] + cur["mru_metadata_target"] 391*dd32d6b2SMartin Matuska 392*dd32d6b2SMartin Matuska for key in cur: 393*dd32d6b2SMartin Matuska if re.match(key, "class"): 394*dd32d6b2SMartin Matuska continue 395*dd32d6b2SMartin Matuska if key in prev: 396*dd32d6b2SMartin Matuska d[key] = cur[key] - prev[key] 397*dd32d6b2SMartin Matuska else: 398*dd32d6b2SMartin Matuska d[key] = cur[key] 399*dd32d6b2SMartin Matuska 400*dd32d6b2SMartin Matuska 401*dd32d6b2SMartin Matuskadef isint(num): 402*dd32d6b2SMartin Matuska if isinstance(num, float): 403*dd32d6b2SMartin Matuska return num.is_integer() 404*dd32d6b2SMartin Matuska if isinstance(num, int): 405*dd32d6b2SMartin Matuska return True 406*dd32d6b2SMartin Matuska return False 407*dd32d6b2SMartin Matuska 408*dd32d6b2SMartin Matuska 409*dd32d6b2SMartin Matuskadef prettynum(sz, scale, num=0): 410*dd32d6b2SMartin Matuska suffix = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z'] 411*dd32d6b2SMartin Matuska index = 0 412*dd32d6b2SMartin Matuska 413*dd32d6b2SMartin Matuska # Special case for date field 414*dd32d6b2SMartin Matuska if scale == -1: 415*dd32d6b2SMartin Matuska return "%s" % num 416*dd32d6b2SMartin Matuska 417*dd32d6b2SMartin Matuska if scale != 100: 418*dd32d6b2SMartin Matuska while abs(num) > scale and index < 5: 419*dd32d6b2SMartin Matuska num = num / scale 420*dd32d6b2SMartin Matuska index += 1 421*dd32d6b2SMartin Matuska 422*dd32d6b2SMartin Matuska width = sz - (0 if index == 0 else 1) 423*dd32d6b2SMartin Matuska intlen = len("%.0f" % num) # %.0f rounds to nearest int 424*dd32d6b2SMartin Matuska if sint == 1 and isint(num) or width < intlen + 2: 425*dd32d6b2SMartin Matuska decimal = 0 426*dd32d6b2SMartin Matuska else: 427*dd32d6b2SMartin Matuska decimal = 1 428*dd32d6b2SMartin Matuska return "%*.*f%s" % (width, decimal, num, suffix[index]) 429*dd32d6b2SMartin Matuska 430*dd32d6b2SMartin Matuska 431*dd32d6b2SMartin Matuskadef print_values(): 432*dd32d6b2SMartin Matuska global hdr 433*dd32d6b2SMartin Matuska global sep 434*dd32d6b2SMartin Matuska global v 435*dd32d6b2SMartin Matuska global pretty_print 436*dd32d6b2SMartin Matuska 437*dd32d6b2SMartin Matuska if pretty_print: 438*dd32d6b2SMartin Matuska fmt = lambda col: prettynum(cols[col][0], cols[col][1], v[col]) 439*dd32d6b2SMartin Matuska else: 440*dd32d6b2SMartin Matuska fmt = lambda col: str(v[col]) 441*dd32d6b2SMartin Matuska 442*dd32d6b2SMartin Matuska sys.stdout.write(sep.join(fmt(col) for col in hdr)) 443*dd32d6b2SMartin Matuska sys.stdout.write("\n") 444*dd32d6b2SMartin Matuska sys.stdout.flush() 445*dd32d6b2SMartin Matuska 446*dd32d6b2SMartin Matuska 447*dd32d6b2SMartin Matuskadef print_header(): 448*dd32d6b2SMartin Matuska global hdr 449*dd32d6b2SMartin Matuska global sep 450*dd32d6b2SMartin Matuska global pretty_print 451*dd32d6b2SMartin Matuska 452*dd32d6b2SMartin Matuska if pretty_print: 453*dd32d6b2SMartin Matuska fmt = lambda col: "%*s" % (cols[col][0], col) 454*dd32d6b2SMartin Matuska else: 455*dd32d6b2SMartin Matuska fmt = lambda col: col 456*dd32d6b2SMartin Matuska 457*dd32d6b2SMartin Matuska sys.stdout.write(sep.join(fmt(col) for col in hdr)) 458*dd32d6b2SMartin Matuska sys.stdout.write("\n") 459*dd32d6b2SMartin Matuska 460*dd32d6b2SMartin Matuska 461*dd32d6b2SMartin Matuskadef get_terminal_lines(): 462*dd32d6b2SMartin Matuska try: 463*dd32d6b2SMartin Matuska import fcntl 464*dd32d6b2SMartin Matuska import termios 465*dd32d6b2SMartin Matuska import struct 466*dd32d6b2SMartin Matuska data = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, '1234') 467*dd32d6b2SMartin Matuska sz = struct.unpack('hh', data) 468*dd32d6b2SMartin Matuska return sz[0] 469*dd32d6b2SMartin Matuska except Exception: 470*dd32d6b2SMartin Matuska pass 471*dd32d6b2SMartin Matuska 472*dd32d6b2SMartin Matuska 473*dd32d6b2SMartin Matuskadef update_hdr_intr(): 474*dd32d6b2SMartin Matuska global hdr_intr 475*dd32d6b2SMartin Matuska 476*dd32d6b2SMartin Matuska lines = get_terminal_lines() 477*dd32d6b2SMartin Matuska if lines and lines > 3: 478*dd32d6b2SMartin Matuska hdr_intr = lines - 3 479*dd32d6b2SMartin Matuska 480*dd32d6b2SMartin Matuska 481*dd32d6b2SMartin Matuskadef resize_handler(signum, frame): 482*dd32d6b2SMartin Matuska update_hdr_intr() 483*dd32d6b2SMartin Matuska 484*dd32d6b2SMartin Matuska 485*dd32d6b2SMartin Matuskadef init(): 486*dd32d6b2SMartin Matuska global sint 487*dd32d6b2SMartin Matuska global count 488*dd32d6b2SMartin Matuska global hdr 489*dd32d6b2SMartin Matuska global xhdr 490*dd32d6b2SMartin Matuska global zhdr 491*dd32d6b2SMartin Matuska global opfile 492*dd32d6b2SMartin Matuska global sep 493*dd32d6b2SMartin Matuska global out 494*dd32d6b2SMartin Matuska global l2exist 495*dd32d6b2SMartin Matuska global pretty_print 496*dd32d6b2SMartin Matuska 497*dd32d6b2SMartin Matuska desired_cols = None 498*dd32d6b2SMartin Matuska aflag = False 499*dd32d6b2SMartin Matuska xflag = False 500*dd32d6b2SMartin Matuska hflag = False 501*dd32d6b2SMartin Matuska vflag = False 502*dd32d6b2SMartin Matuska zflag = False 503*dd32d6b2SMartin Matuska i = 1 504*dd32d6b2SMartin Matuska 505*dd32d6b2SMartin Matuska try: 506*dd32d6b2SMartin Matuska opts, args = getopt.getopt( 507*dd32d6b2SMartin Matuska sys.argv[1:], 508*dd32d6b2SMartin Matuska "axzo:hvs:f:p", 509*dd32d6b2SMartin Matuska [ 510*dd32d6b2SMartin Matuska "all", 511*dd32d6b2SMartin Matuska "extended", 512*dd32d6b2SMartin Matuska "zfetch", 513*dd32d6b2SMartin Matuska "outfile", 514*dd32d6b2SMartin Matuska "help", 515*dd32d6b2SMartin Matuska "verbose", 516*dd32d6b2SMartin Matuska "separator", 517*dd32d6b2SMartin Matuska "columns", 518*dd32d6b2SMartin Matuska "parsable" 519*dd32d6b2SMartin Matuska ] 520*dd32d6b2SMartin Matuska ) 521*dd32d6b2SMartin Matuska except getopt.error as msg: 522*dd32d6b2SMartin Matuska sys.stderr.write("Error: %s\n" % str(msg)) 523*dd32d6b2SMartin Matuska usage() 524*dd32d6b2SMartin Matuska opts = None 525*dd32d6b2SMartin Matuska 526*dd32d6b2SMartin Matuska for opt, arg in opts: 527*dd32d6b2SMartin Matuska if opt in ('-a', '--all'): 528*dd32d6b2SMartin Matuska aflag = True 529*dd32d6b2SMartin Matuska if opt in ('-x', '--extended'): 530*dd32d6b2SMartin Matuska xflag = True 531*dd32d6b2SMartin Matuska if opt in ('-o', '--outfile'): 532*dd32d6b2SMartin Matuska opfile = arg 533*dd32d6b2SMartin Matuska i += 1 534*dd32d6b2SMartin Matuska if opt in ('-h', '--help'): 535*dd32d6b2SMartin Matuska hflag = True 536*dd32d6b2SMartin Matuska if opt in ('-v', '--verbose'): 537*dd32d6b2SMartin Matuska vflag = True 538*dd32d6b2SMartin Matuska if opt in ('-s', '--separator'): 539*dd32d6b2SMartin Matuska sep = arg 540*dd32d6b2SMartin Matuska i += 1 541*dd32d6b2SMartin Matuska if opt in ('-f', '--columns'): 542*dd32d6b2SMartin Matuska desired_cols = arg 543*dd32d6b2SMartin Matuska i += 1 544*dd32d6b2SMartin Matuska if opt in ('-p', '--parsable'): 545*dd32d6b2SMartin Matuska pretty_print = False 546*dd32d6b2SMartin Matuska if opt in ('-z', '--zfetch'): 547*dd32d6b2SMartin Matuska zflag = True 548*dd32d6b2SMartin Matuska i += 1 549*dd32d6b2SMartin Matuska 550*dd32d6b2SMartin Matuska argv = sys.argv[i:] 551*dd32d6b2SMartin Matuska sint = int(argv[0]) if argv else sint 552*dd32d6b2SMartin Matuska count = int(argv[1]) if len(argv) > 1 else (0 if len(argv) > 0 else 1) 553*dd32d6b2SMartin Matuska 554*dd32d6b2SMartin Matuska if hflag or (xflag and zflag) or ((zflag or xflag) and desired_cols): 555*dd32d6b2SMartin Matuska usage() 556*dd32d6b2SMartin Matuska 557*dd32d6b2SMartin Matuska if vflag: 558*dd32d6b2SMartin Matuska detailed_usage() 559*dd32d6b2SMartin Matuska 560*dd32d6b2SMartin Matuska if xflag: 561*dd32d6b2SMartin Matuska hdr = xhdr 562*dd32d6b2SMartin Matuska 563*dd32d6b2SMartin Matuska if zflag: 564*dd32d6b2SMartin Matuska hdr = zhdr 565*dd32d6b2SMartin Matuska 566*dd32d6b2SMartin Matuska update_hdr_intr() 567*dd32d6b2SMartin Matuska 568*dd32d6b2SMartin Matuska # check if L2ARC exists 569*dd32d6b2SMartin Matuska snap_stats() 570*dd32d6b2SMartin Matuska l2_size = cur.get("l2_size") 571*dd32d6b2SMartin Matuska if l2_size: 572*dd32d6b2SMartin Matuska l2exist = True 573*dd32d6b2SMartin Matuska 574*dd32d6b2SMartin Matuska if desired_cols: 575*dd32d6b2SMartin Matuska hdr = desired_cols.split(",") 576*dd32d6b2SMartin Matuska 577*dd32d6b2SMartin Matuska invalid = [] 578*dd32d6b2SMartin Matuska incompat = [] 579*dd32d6b2SMartin Matuska for ele in hdr: 580*dd32d6b2SMartin Matuska if ele not in cols: 581*dd32d6b2SMartin Matuska invalid.append(ele) 582*dd32d6b2SMartin Matuska elif not l2exist and ele.startswith("l2"): 583*dd32d6b2SMartin Matuska sys.stdout.write("No L2ARC Here\n%s\n" % ele) 584*dd32d6b2SMartin Matuska incompat.append(ele) 585*dd32d6b2SMartin Matuska 586*dd32d6b2SMartin Matuska if len(invalid) > 0: 587*dd32d6b2SMartin Matuska sys.stderr.write("Invalid column definition! -- %s\n" % invalid) 588*dd32d6b2SMartin Matuska usage() 589*dd32d6b2SMartin Matuska 590*dd32d6b2SMartin Matuska if len(incompat) > 0: 591*dd32d6b2SMartin Matuska sys.stderr.write("Incompatible field specified! -- %s\n" % 592*dd32d6b2SMartin Matuska incompat) 593*dd32d6b2SMartin Matuska usage() 594*dd32d6b2SMartin Matuska 595*dd32d6b2SMartin Matuska if aflag: 596*dd32d6b2SMartin Matuska if l2exist: 597*dd32d6b2SMartin Matuska hdr = cols.keys() 598*dd32d6b2SMartin Matuska else: 599*dd32d6b2SMartin Matuska hdr = [col for col in cols.keys() if not col.startswith("l2")] 600*dd32d6b2SMartin Matuska 601*dd32d6b2SMartin Matuska if opfile: 602*dd32d6b2SMartin Matuska try: 603*dd32d6b2SMartin Matuska out = open(opfile, "w") 604*dd32d6b2SMartin Matuska sys.stdout = out 605*dd32d6b2SMartin Matuska 606*dd32d6b2SMartin Matuska except IOError: 607*dd32d6b2SMartin Matuska sys.stderr.write("Cannot open %s for writing\n" % opfile) 608*dd32d6b2SMartin Matuska sys.exit(1) 609*dd32d6b2SMartin Matuska 610*dd32d6b2SMartin Matuska 611*dd32d6b2SMartin Matuskadef calculate(): 612*dd32d6b2SMartin Matuska global d 613*dd32d6b2SMartin Matuska global v 614*dd32d6b2SMartin Matuska global l2exist 615*dd32d6b2SMartin Matuska 616*dd32d6b2SMartin Matuska v = dict() 617*dd32d6b2SMartin Matuska v["time"] = time.strftime("%H:%M:%S", time.localtime()) 618*dd32d6b2SMartin Matuska v["hits"] = d["hits"] / sint 619*dd32d6b2SMartin Matuska v["iohs"] = d["iohits"] / sint 620*dd32d6b2SMartin Matuska v["miss"] = d["misses"] / sint 621*dd32d6b2SMartin Matuska v["read"] = v["hits"] + v["iohs"] + v["miss"] 622*dd32d6b2SMartin Matuska v["hit%"] = 100 * v["hits"] / v["read"] if v["read"] > 0 else 0 623*dd32d6b2SMartin Matuska v["ioh%"] = 100 * v["iohs"] / v["read"] if v["read"] > 0 else 0 624*dd32d6b2SMartin Matuska v["miss%"] = 100 - v["hit%"] - v["ioh%"] if v["read"] > 0 else 0 625*dd32d6b2SMartin Matuska 626*dd32d6b2SMartin Matuska v["dhit"] = (d["demand_data_hits"] + d["demand_metadata_hits"]) / sint 627*dd32d6b2SMartin Matuska v["dioh"] = (d["demand_data_iohits"] + d["demand_metadata_iohits"]) / sint 628*dd32d6b2SMartin Matuska v["dmis"] = (d["demand_data_misses"] + d["demand_metadata_misses"]) / sint 629*dd32d6b2SMartin Matuska 630*dd32d6b2SMartin Matuska v["dread"] = v["dhit"] + v["dioh"] + v["dmis"] 631*dd32d6b2SMartin Matuska v["dh%"] = 100 * v["dhit"] / v["dread"] if v["dread"] > 0 else 0 632*dd32d6b2SMartin Matuska v["di%"] = 100 * v["dioh"] / v["dread"] if v["dread"] > 0 else 0 633*dd32d6b2SMartin Matuska v["dm%"] = 100 - v["dh%"] - v["di%"] if v["dread"] > 0 else 0 634*dd32d6b2SMartin Matuska 635*dd32d6b2SMartin Matuska v["ddhit"] = d["demand_data_hits"] / sint 636*dd32d6b2SMartin Matuska v["ddioh"] = d["demand_data_iohits"] / sint 637*dd32d6b2SMartin Matuska v["ddmis"] = d["demand_data_misses"] / sint 638*dd32d6b2SMartin Matuska 639*dd32d6b2SMartin Matuska v["ddread"] = v["ddhit"] + v["ddioh"] + v["ddmis"] 640*dd32d6b2SMartin Matuska v["ddh%"] = 100 * v["ddhit"] / v["ddread"] if v["ddread"] > 0 else 0 641*dd32d6b2SMartin Matuska v["ddi%"] = 100 * v["ddioh"] / v["ddread"] if v["ddread"] > 0 else 0 642*dd32d6b2SMartin Matuska v["ddm%"] = 100 - v["ddh%"] - v["ddi%"] if v["ddread"] > 0 else 0 643*dd32d6b2SMartin Matuska 644*dd32d6b2SMartin Matuska v["dmhit"] = d["demand_metadata_hits"] / sint 645*dd32d6b2SMartin Matuska v["dmioh"] = d["demand_metadata_iohits"] / sint 646*dd32d6b2SMartin Matuska v["dmmis"] = d["demand_metadata_misses"] / sint 647*dd32d6b2SMartin Matuska 648*dd32d6b2SMartin Matuska v["dmread"] = v["dmhit"] + v["dmioh"] + v["dmmis"] 649*dd32d6b2SMartin Matuska v["dmh%"] = 100 * v["dmhit"] / v["dmread"] if v["dmread"] > 0 else 0 650*dd32d6b2SMartin Matuska v["dmi%"] = 100 * v["dmioh"] / v["dmread"] if v["dmread"] > 0 else 0 651*dd32d6b2SMartin Matuska v["dmm%"] = 100 - v["dmh%"] - v["dmi%"] if v["dmread"] > 0 else 0 652*dd32d6b2SMartin Matuska 653*dd32d6b2SMartin Matuska v["phit"] = (d["prefetch_data_hits"] + d["prefetch_metadata_hits"]) / sint 654*dd32d6b2SMartin Matuska v["pioh"] = (d["prefetch_data_iohits"] + 655*dd32d6b2SMartin Matuska d["prefetch_metadata_iohits"]) / sint 656*dd32d6b2SMartin Matuska v["pmis"] = (d["prefetch_data_misses"] + 657*dd32d6b2SMartin Matuska d["prefetch_metadata_misses"]) / sint 658*dd32d6b2SMartin Matuska 659*dd32d6b2SMartin Matuska v["pread"] = v["phit"] + v["pioh"] + v["pmis"] 660*dd32d6b2SMartin Matuska v["ph%"] = 100 * v["phit"] / v["pread"] if v["pread"] > 0 else 0 661*dd32d6b2SMartin Matuska v["pi%"] = 100 * v["pioh"] / v["pread"] if v["pread"] > 0 else 0 662*dd32d6b2SMartin Matuska v["pm%"] = 100 - v["ph%"] - v["pi%"] if v["pread"] > 0 else 0 663*dd32d6b2SMartin Matuska 664*dd32d6b2SMartin Matuska v["pdhit"] = d["prefetch_data_hits"] / sint 665*dd32d6b2SMartin Matuska v["pdioh"] = d["prefetch_data_iohits"] / sint 666*dd32d6b2SMartin Matuska v["pdmis"] = d["prefetch_data_misses"] / sint 667*dd32d6b2SMartin Matuska 668*dd32d6b2SMartin Matuska v["pdread"] = v["pdhit"] + v["pdioh"] + v["pdmis"] 669*dd32d6b2SMartin Matuska v["pdh%"] = 100 * v["pdhit"] / v["pdread"] if v["pdread"] > 0 else 0 670*dd32d6b2SMartin Matuska v["pdi%"] = 100 * v["pdioh"] / v["pdread"] if v["pdread"] > 0 else 0 671*dd32d6b2SMartin Matuska v["pdm%"] = 100 - v["pdh%"] - v["pdi%"] if v["pdread"] > 0 else 0 672*dd32d6b2SMartin Matuska 673*dd32d6b2SMartin Matuska v["pmhit"] = d["prefetch_metadata_hits"] / sint 674*dd32d6b2SMartin Matuska v["pmioh"] = d["prefetch_metadata_iohits"] / sint 675*dd32d6b2SMartin Matuska v["pmmis"] = d["prefetch_metadata_misses"] / sint 676*dd32d6b2SMartin Matuska 677*dd32d6b2SMartin Matuska v["pmread"] = v["pmhit"] + v["pmioh"] + v["pmmis"] 678*dd32d6b2SMartin Matuska v["pmh%"] = 100 * v["pmhit"] / v["pmread"] if v["pmread"] > 0 else 0 679*dd32d6b2SMartin Matuska v["pmi%"] = 100 * v["pmioh"] / v["pmread"] if v["pmread"] > 0 else 0 680*dd32d6b2SMartin Matuska v["pmm%"] = 100 - v["pmh%"] - v["pmi%"] if v["pmread"] > 0 else 0 681*dd32d6b2SMartin Matuska 682*dd32d6b2SMartin Matuska v["mhit"] = (d["prefetch_metadata_hits"] + 683*dd32d6b2SMartin Matuska d["demand_metadata_hits"]) / sint 684*dd32d6b2SMartin Matuska v["mioh"] = (d["prefetch_metadata_iohits"] + 685*dd32d6b2SMartin Matuska d["demand_metadata_iohits"]) / sint 686*dd32d6b2SMartin Matuska v["mmis"] = (d["prefetch_metadata_misses"] + 687*dd32d6b2SMartin Matuska d["demand_metadata_misses"]) / sint 688*dd32d6b2SMartin Matuska 689*dd32d6b2SMartin Matuska v["mread"] = v["mhit"] + v["mioh"] + v["mmis"] 690*dd32d6b2SMartin Matuska v["mh%"] = 100 * v["mhit"] / v["mread"] if v["mread"] > 0 else 0 691*dd32d6b2SMartin Matuska v["mi%"] = 100 * v["mioh"] / v["mread"] if v["mread"] > 0 else 0 692*dd32d6b2SMartin Matuska v["mm%"] = 100 - v["mh%"] - v["mi%"] if v["mread"] > 0 else 0 693*dd32d6b2SMartin Matuska 694*dd32d6b2SMartin Matuska v["arcsz"] = cur["size"] 695*dd32d6b2SMartin Matuska v["size"] = cur["size"] 696*dd32d6b2SMartin Matuska v["c"] = cur["c"] 697*dd32d6b2SMartin Matuska v["mfu"] = d["mfu_hits"] / sint 698*dd32d6b2SMartin Matuska v["mru"] = d["mru_hits"] / sint 699*dd32d6b2SMartin Matuska v["mrug"] = d["mru_ghost_hits"] / sint 700*dd32d6b2SMartin Matuska v["mfug"] = d["mfu_ghost_hits"] / sint 701*dd32d6b2SMartin Matuska v["unc"] = d["uncached_hits"] / sint 702*dd32d6b2SMartin Matuska v["eskip"] = d["evict_skip"] / sint 703*dd32d6b2SMartin Matuska v["el2skip"] = d["evict_l2_skip"] / sint 704*dd32d6b2SMartin Matuska v["el2cach"] = d["evict_l2_cached"] / sint 705*dd32d6b2SMartin Matuska v["el2el"] = d["evict_l2_eligible"] / sint 706*dd32d6b2SMartin Matuska v["el2mfu"] = d["evict_l2_eligible_mfu"] / sint 707*dd32d6b2SMartin Matuska v["el2mru"] = d["evict_l2_eligible_mru"] / sint 708*dd32d6b2SMartin Matuska v["el2inel"] = d["evict_l2_ineligible"] / sint 709*dd32d6b2SMartin Matuska v["mtxmis"] = d["mutex_miss"] / sint 710*dd32d6b2SMartin Matuska v["ztotal"] = (d["zfetch_hits"] + d["zfetch_future"] + d["zfetch_stride"] + 711*dd32d6b2SMartin Matuska d["zfetch_past"] + d["zfetch_misses"]) / sint 712*dd32d6b2SMartin Matuska v["zhits"] = d["zfetch_hits"] / sint 713*dd32d6b2SMartin Matuska v["zahead"] = (d["zfetch_future"] + d["zfetch_stride"]) / sint 714*dd32d6b2SMartin Matuska v["zpast"] = d["zfetch_past"] / sint 715*dd32d6b2SMartin Matuska v["zmisses"] = d["zfetch_misses"] / sint 716*dd32d6b2SMartin Matuska v["zmax"] = d["zfetch_max_streams"] / sint 717*dd32d6b2SMartin Matuska v["zfuture"] = d["zfetch_future"] / sint 718*dd32d6b2SMartin Matuska v["zstride"] = d["zfetch_stride"] / sint 719*dd32d6b2SMartin Matuska v["zissued"] = d["zfetch_io_issued"] / sint 720*dd32d6b2SMartin Matuska v["zactive"] = d["zfetch_io_active"] / sint 721*dd32d6b2SMartin Matuska 722*dd32d6b2SMartin Matuska # ARC structural breakdown, ARC types breakdown, ARC states breakdown 723*dd32d6b2SMartin Matuska v["cachessz"] = cur["caches_size"] 724*dd32d6b2SMartin Matuska for fs in fieldstats: 725*dd32d6b2SMartin Matuska fields, stats = fs[0], fs[1:] 726*dd32d6b2SMartin Matuska for field, fieldval in fields.items(): 727*dd32d6b2SMartin Matuska for group in stats: 728*dd32d6b2SMartin Matuska for stat, statval in group.items(): 729*dd32d6b2SMartin Matuska if stat in ["fields", "percent"] or \ 730*dd32d6b2SMartin Matuska ("fields" in group and field not in group["fields"]): 731*dd32d6b2SMartin Matuska continue 732*dd32d6b2SMartin Matuska colname = field + stat 733*dd32d6b2SMartin Matuska v[colname] = cur[fieldval[0] + statval[0]] 734*dd32d6b2SMartin Matuska if "percent" in group: 735*dd32d6b2SMartin Matuska v[colname + "%"] = 100 * v[colname] / \ 736*dd32d6b2SMartin Matuska v[group["percent"]] if v[group["percent"]] > 0 else 0 737*dd32d6b2SMartin Matuska 738*dd32d6b2SMartin Matuska if l2exist: 739*dd32d6b2SMartin Matuska l2asize = cur["l2_asize"] 740*dd32d6b2SMartin Matuska v["l2hits"] = d["l2_hits"] / sint 741*dd32d6b2SMartin Matuska v["l2miss"] = d["l2_misses"] / sint 742*dd32d6b2SMartin Matuska v["l2read"] = v["l2hits"] + v["l2miss"] 743*dd32d6b2SMartin Matuska v["l2hit%"] = 100 * v["l2hits"] / v["l2read"] if v["l2read"] > 0 else 0 744*dd32d6b2SMartin Matuska 745*dd32d6b2SMartin Matuska v["l2miss%"] = 100 - v["l2hit%"] if v["l2read"] > 0 else 0 746*dd32d6b2SMartin Matuska v["l2asize"] = l2asize 747*dd32d6b2SMartin Matuska v["l2size"] = cur["l2_size"] 748*dd32d6b2SMartin Matuska v["l2bytes"] = d["l2_read_bytes"] / sint 749*dd32d6b2SMartin Matuska v["l2wbytes"] = d["l2_write_bytes"] / sint 750*dd32d6b2SMartin Matuska 751*dd32d6b2SMartin Matuska v["l2pref"] = cur["l2_prefetch_asize"] 752*dd32d6b2SMartin Matuska v["l2mfu"] = cur["l2_mfu_asize"] 753*dd32d6b2SMartin Matuska v["l2mru"] = cur["l2_mru_asize"] 754*dd32d6b2SMartin Matuska v["l2data"] = cur["l2_bufc_data_asize"] 755*dd32d6b2SMartin Matuska v["l2meta"] = cur["l2_bufc_metadata_asize"] 756*dd32d6b2SMartin Matuska v["l2pref%"] = 100 * v["l2pref"] / l2asize if l2asize > 0 else 0 757*dd32d6b2SMartin Matuska v["l2mfu%"] = 100 * v["l2mfu"] / l2asize if l2asize > 0 else 0 758*dd32d6b2SMartin Matuska v["l2mru%"] = 100 * v["l2mru"] / l2asize if l2asize > 0 else 0 759*dd32d6b2SMartin Matuska v["l2data%"] = 100 * v["l2data"] / l2asize if l2asize > 0 else 0 760*dd32d6b2SMartin Matuska v["l2meta%"] = 100 * v["l2meta"] / l2asize if l2asize > 0 else 0 761*dd32d6b2SMartin Matuska 762*dd32d6b2SMartin Matuska v["grow"] = 0 if cur["arc_no_grow"] else 1 763*dd32d6b2SMartin Matuska v["need"] = cur["arc_need_free"] 764*dd32d6b2SMartin Matuska v["free"] = cur["memory_free_bytes"] 765*dd32d6b2SMartin Matuska v["avail"] = cur["memory_available_bytes"] 766*dd32d6b2SMartin Matuska v["waste"] = cur["abd_chunk_waste_size"] 767*dd32d6b2SMartin Matuska 768*dd32d6b2SMartin Matuska 769*dd32d6b2SMartin Matuskadef main(): 770*dd32d6b2SMartin Matuska 771*dd32d6b2SMartin Matuska global sint 772*dd32d6b2SMartin Matuska global count 773*dd32d6b2SMartin Matuska global hdr_intr 774*dd32d6b2SMartin Matuska 775*dd32d6b2SMartin Matuska i = 0 776*dd32d6b2SMartin Matuska count_flag = 0 777*dd32d6b2SMartin Matuska 778*dd32d6b2SMartin Matuska init() 779*dd32d6b2SMartin Matuska if count > 0: 780*dd32d6b2SMartin Matuska count_flag = 1 781*dd32d6b2SMartin Matuska 782*dd32d6b2SMartin Matuska signal(SIGINT, SIG_DFL) 783*dd32d6b2SMartin Matuska signal(SIGWINCH, resize_handler) 784*dd32d6b2SMartin Matuska while True: 785*dd32d6b2SMartin Matuska if i == 0: 786*dd32d6b2SMartin Matuska print_header() 787*dd32d6b2SMartin Matuska 788*dd32d6b2SMartin Matuska snap_stats() 789*dd32d6b2SMartin Matuska calculate() 790*dd32d6b2SMartin Matuska print_values() 791*dd32d6b2SMartin Matuska 792*dd32d6b2SMartin Matuska if count_flag == 1: 793*dd32d6b2SMartin Matuska if count <= 1: 794*dd32d6b2SMartin Matuska break 795*dd32d6b2SMartin Matuska count -= 1 796*dd32d6b2SMartin Matuska 797*dd32d6b2SMartin Matuska i = 0 if i >= hdr_intr else i + 1 798*dd32d6b2SMartin Matuska time.sleep(sint) 799*dd32d6b2SMartin Matuska 800*dd32d6b2SMartin Matuska if out: 801*dd32d6b2SMartin Matuska out.close() 802*dd32d6b2SMartin Matuska 803*dd32d6b2SMartin Matuska 804*dd32d6b2SMartin Matuskaif __name__ == '__main__': 805*dd32d6b2SMartin Matuska main() 806