1716fd348SMartin Matuska#!/usr/bin/env @PYTHON_SHEBANG@ 2*61145dc2SMartin Matuska# SPDX-License-Identifier: CDDL-1.0 3716fd348SMartin Matuska# 4716fd348SMartin Matuska# Print out ZFS ARC Statistics exported via kstat(1) 5716fd348SMartin Matuska# For a definition of fields, or usage, use arcstat -v 6716fd348SMartin Matuska# 7716fd348SMartin Matuska# This script was originally a fork of the original arcstat.pl (0.1) 8716fd348SMartin Matuska# by Neelakanth Nadgir, originally published on his Sun blog on 9716fd348SMartin Matuska# 09/18/2007 10716fd348SMartin Matuska# http://blogs.sun.com/realneel/entry/zfs_arc_statistics 11716fd348SMartin Matuska# 12716fd348SMartin Matuska# A new version aimed to improve upon the original by adding features 13716fd348SMartin Matuska# and fixing bugs as needed. This version was maintained by Mike 14716fd348SMartin Matuska# Harsch and was hosted in a public open source repository: 15716fd348SMartin Matuska# http://github.com/mharsch/arcstat 16716fd348SMartin Matuska# 17716fd348SMartin Matuska# but has since moved to the illumos-gate repository. 18716fd348SMartin Matuska# 19716fd348SMartin Matuska# This Python port was written by John Hixson for FreeNAS, introduced 20716fd348SMartin Matuska# in commit e2c29f: 21716fd348SMartin Matuska# https://github.com/freenas/freenas 22716fd348SMartin Matuska# 23716fd348SMartin Matuska# and has been improved by many people since. 24716fd348SMartin Matuska# 25716fd348SMartin Matuska# CDDL HEADER START 26716fd348SMartin Matuska# 27716fd348SMartin Matuska# The contents of this file are subject to the terms of the 28716fd348SMartin Matuska# Common Development and Distribution License, Version 1.0 only 29716fd348SMartin Matuska# (the "License"). You may not use this file except in compliance 30716fd348SMartin Matuska# with the License. 31716fd348SMartin Matuska# 32716fd348SMartin Matuska# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 33271171e0SMartin Matuska# or https://opensource.org/licenses/CDDL-1.0. 34716fd348SMartin Matuska# See the License for the specific language governing permissions 35716fd348SMartin Matuska# and limitations under the License. 36716fd348SMartin Matuska# 37716fd348SMartin Matuska# When distributing Covered Code, include this CDDL HEADER in each 38716fd348SMartin Matuska# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 39716fd348SMartin Matuska# If applicable, add the following below this CDDL HEADER, with the 40716fd348SMartin Matuska# fields enclosed by brackets "[]" replaced with your own identifying 41716fd348SMartin Matuska# information: Portions Copyright [yyyy] [name of copyright owner] 42716fd348SMartin Matuska# 43716fd348SMartin Matuska# CDDL HEADER END 44716fd348SMartin Matuska# 45716fd348SMartin Matuska# 46716fd348SMartin Matuska# Fields have a fixed width. Every interval, we fill the "v" 47716fd348SMartin Matuska# hash with its corresponding value (v[field]=value) using calculate(). 48716fd348SMartin Matuska# @hdr is the array of fields that needs to be printed, so we 49716fd348SMartin Matuska# just iterate over this array and print the values using our pretty printer. 50716fd348SMartin Matuska# 51716fd348SMartin Matuska# This script must remain compatible with Python 3.6+. 52716fd348SMartin Matuska# 53716fd348SMartin Matuska 54716fd348SMartin Matuskaimport sys 55716fd348SMartin Matuskaimport time 56716fd348SMartin Matuskaimport getopt 57716fd348SMartin Matuskaimport re 58716fd348SMartin Matuskaimport copy 59716fd348SMartin Matuska 60716fd348SMartin Matuskafrom signal import signal, SIGINT, SIGWINCH, SIG_DFL 61716fd348SMartin Matuska 62716fd348SMartin Matuska 63716fd348SMartin Matuskacols = { 64716fd348SMartin Matuska # HDR: [Size, Scale, Description] 65716fd348SMartin Matuska "time": [8, -1, "Time"], 6615f0b8c3SMartin Matuska "hits": [4, 1000, "ARC hits per second"], 6715f0b8c3SMartin Matuska "iohs": [4, 1000, "ARC I/O hits per second"], 68716fd348SMartin Matuska "miss": [4, 1000, "ARC misses per second"], 69716fd348SMartin Matuska "read": [4, 1000, "Total ARC accesses per second"], 70716fd348SMartin Matuska "hit%": [4, 100, "ARC hit percentage"], 7115f0b8c3SMartin Matuska "ioh%": [4, 100, "ARC I/O hit percentage"], 72716fd348SMartin Matuska "miss%": [5, 100, "ARC miss percentage"], 73716fd348SMartin Matuska "dhit": [4, 1000, "Demand hits per second"], 7415f0b8c3SMartin Matuska "dioh": [4, 1000, "Demand I/O hits per second"], 75716fd348SMartin Matuska "dmis": [4, 1000, "Demand misses per second"], 76716fd348SMartin Matuska "dh%": [3, 100, "Demand hit percentage"], 7715f0b8c3SMartin Matuska "di%": [3, 100, "Demand I/O hit percentage"], 78716fd348SMartin Matuska "dm%": [3, 100, "Demand miss percentage"], 7915f0b8c3SMartin Matuska "ddhit": [5, 1000, "Demand data hits per second"], 8015f0b8c3SMartin Matuska "ddioh": [5, 1000, "Demand data I/O hits per second"], 8115f0b8c3SMartin Matuska "ddmis": [5, 1000, "Demand data misses per second"], 8215f0b8c3SMartin Matuska "ddh%": [4, 100, "Demand data hit percentage"], 8315f0b8c3SMartin Matuska "ddi%": [4, 100, "Demand data I/O hit percentage"], 8415f0b8c3SMartin Matuska "ddm%": [4, 100, "Demand data miss percentage"], 8515f0b8c3SMartin Matuska "dmhit": [5, 1000, "Demand metadata hits per second"], 8615f0b8c3SMartin Matuska "dmioh": [5, 1000, "Demand metadata I/O hits per second"], 8715f0b8c3SMartin Matuska "dmmis": [5, 1000, "Demand metadata misses per second"], 8815f0b8c3SMartin Matuska "dmh%": [4, 100, "Demand metadata hit percentage"], 8915f0b8c3SMartin Matuska "dmi%": [4, 100, "Demand metadata I/O hit percentage"], 9015f0b8c3SMartin Matuska "dmm%": [4, 100, "Demand metadata miss percentage"], 91716fd348SMartin Matuska "phit": [4, 1000, "Prefetch hits per second"], 9215f0b8c3SMartin Matuska "pioh": [4, 1000, "Prefetch I/O hits per second"], 93716fd348SMartin Matuska "pmis": [4, 1000, "Prefetch misses per second"], 94716fd348SMartin Matuska "ph%": [3, 100, "Prefetch hits percentage"], 9515f0b8c3SMartin Matuska "pi%": [3, 100, "Prefetch I/O hits percentage"], 96716fd348SMartin Matuska "pm%": [3, 100, "Prefetch miss percentage"], 9715f0b8c3SMartin Matuska "pdhit": [5, 1000, "Prefetch data hits per second"], 9815f0b8c3SMartin Matuska "pdioh": [5, 1000, "Prefetch data I/O hits per second"], 9915f0b8c3SMartin Matuska "pdmis": [5, 1000, "Prefetch data misses per second"], 10015f0b8c3SMartin Matuska "pdh%": [4, 100, "Prefetch data hits percentage"], 10115f0b8c3SMartin Matuska "pdi%": [4, 100, "Prefetch data I/O hits percentage"], 10215f0b8c3SMartin Matuska "pdm%": [4, 100, "Prefetch data miss percentage"], 10315f0b8c3SMartin Matuska "pmhit": [5, 1000, "Prefetch metadata hits per second"], 10415f0b8c3SMartin Matuska "pmioh": [5, 1000, "Prefetch metadata I/O hits per second"], 10515f0b8c3SMartin Matuska "pmmis": [5, 1000, "Prefetch metadata misses per second"], 10615f0b8c3SMartin Matuska "pmh%": [4, 100, "Prefetch metadata hits percentage"], 10715f0b8c3SMartin Matuska "pmi%": [4, 100, "Prefetch metadata I/O hits percentage"], 10815f0b8c3SMartin Matuska "pmm%": [4, 100, "Prefetch metadata miss percentage"], 109716fd348SMartin Matuska "mhit": [4, 1000, "Metadata hits per second"], 11015f0b8c3SMartin Matuska "mioh": [4, 1000, "Metadata I/O hits per second"], 111716fd348SMartin Matuska "mmis": [4, 1000, "Metadata misses per second"], 112716fd348SMartin Matuska "mread": [5, 1000, "Metadata accesses per second"], 113716fd348SMartin Matuska "mh%": [3, 100, "Metadata hit percentage"], 11415f0b8c3SMartin Matuska "mi%": [3, 100, "Metadata I/O hit percentage"], 115716fd348SMartin Matuska "mm%": [3, 100, "Metadata miss percentage"], 116716fd348SMartin Matuska "arcsz": [5, 1024, "ARC size"], 11715f0b8c3SMartin Matuska "size": [5, 1024, "ARC size"], 11815f0b8c3SMartin Matuska "c": [5, 1024, "ARC target size"], 119716fd348SMartin Matuska "mfu": [4, 1000, "MFU list hits per second"], 120716fd348SMartin Matuska "mru": [4, 1000, "MRU list hits per second"], 121716fd348SMartin Matuska "mfug": [4, 1000, "MFU ghost list hits per second"], 122716fd348SMartin Matuska "mrug": [4, 1000, "MRU ghost list hits per second"], 12315f0b8c3SMartin Matuska "unc": [4, 1000, "Uncached list hits per second"], 124716fd348SMartin Matuska "eskip": [5, 1000, "evict_skip per second"], 125716fd348SMartin Matuska "el2skip": [7, 1000, "evict skip, due to l2 writes, per second"], 126716fd348SMartin Matuska "el2cach": [7, 1024, "Size of L2 cached evictions per second"], 127716fd348SMartin Matuska "el2el": [5, 1024, "Size of L2 eligible evictions per second"], 128716fd348SMartin Matuska "el2mfu": [6, 1024, "Size of L2 eligible MFU evictions per second"], 129716fd348SMartin Matuska "el2mru": [6, 1024, "Size of L2 eligible MRU evictions per second"], 130716fd348SMartin Matuska "el2inel": [7, 1024, "Size of L2 ineligible evictions per second"], 131716fd348SMartin Matuska "mtxmis": [6, 1000, "mutex_miss per second"], 132716fd348SMartin Matuska "dread": [5, 1000, "Demand accesses per second"], 13315f0b8c3SMartin Matuska "ddread": [6, 1000, "Demand data accesses per second"], 13415f0b8c3SMartin Matuska "dmread": [6, 1000, "Demand metadata accesses per second"], 135716fd348SMartin Matuska "pread": [5, 1000, "Prefetch accesses per second"], 13615f0b8c3SMartin Matuska "pdread": [6, 1000, "Prefetch data accesses per second"], 13715f0b8c3SMartin Matuska "pmread": [6, 1000, "Prefetch metadata accesses per second"], 138716fd348SMartin Matuska "l2hits": [6, 1000, "L2ARC hits per second"], 139716fd348SMartin Matuska "l2miss": [6, 1000, "L2ARC misses per second"], 140716fd348SMartin Matuska "l2read": [6, 1000, "Total L2ARC accesses per second"], 141716fd348SMartin Matuska "l2hit%": [6, 100, "L2ARC access hit percentage"], 142716fd348SMartin Matuska "l2miss%": [7, 100, "L2ARC access miss percentage"], 143716fd348SMartin Matuska "l2pref": [6, 1024, "L2ARC prefetch allocated size"], 144716fd348SMartin Matuska "l2mfu": [5, 1024, "L2ARC MFU allocated size"], 145716fd348SMartin Matuska "l2mru": [5, 1024, "L2ARC MRU allocated size"], 146716fd348SMartin Matuska "l2data": [6, 1024, "L2ARC data allocated size"], 147716fd348SMartin Matuska "l2meta": [6, 1024, "L2ARC metadata allocated size"], 148716fd348SMartin Matuska "l2pref%": [7, 100, "L2ARC prefetch percentage"], 149716fd348SMartin Matuska "l2mfu%": [6, 100, "L2ARC MFU percentage"], 150716fd348SMartin Matuska "l2mru%": [6, 100, "L2ARC MRU percentage"], 151716fd348SMartin Matuska "l2data%": [7, 100, "L2ARC data percentage"], 152716fd348SMartin Matuska "l2meta%": [7, 100, "L2ARC metadata percentage"], 153716fd348SMartin Matuska "l2asize": [7, 1024, "Actual (compressed) size of the L2ARC"], 154716fd348SMartin Matuska "l2size": [6, 1024, "Size of the L2ARC"], 155716fd348SMartin Matuska "l2bytes": [7, 1024, "Bytes read per second from the L2ARC"], 1567a7741afSMartin Matuska "l2wbytes": [8, 1024, "Bytes written per second to the L2ARC"], 157716fd348SMartin Matuska "grow": [4, 1000, "ARC grow disabled"], 15815f0b8c3SMartin Matuska "need": [5, 1024, "ARC reclaim need"], 15915f0b8c3SMartin Matuska "free": [5, 1024, "ARC free memory"], 160716fd348SMartin Matuska "avail": [5, 1024, "ARC available memory"], 161716fd348SMartin Matuska "waste": [5, 1024, "Wasted memory due to round up to pagesize"], 1620d4ad640SMartin Matuska "ztotal": [6, 1000, "zfetch total prefetcher calls per second"], 1630d4ad640SMartin Matuska "zhits": [5, 1000, "zfetch stream hits per second"], 1640d4ad640SMartin Matuska "zahead": [6, 1000, "zfetch hits ahead of streams per second"], 1650d4ad640SMartin Matuska "zpast": [5, 1000, "zfetch hits behind streams per second"], 1660d4ad640SMartin Matuska "zmisses": [7, 1000, "zfetch stream misses per second"], 1670d4ad640SMartin Matuska "zmax": [4, 1000, "zfetch limit reached per second"], 1680d4ad640SMartin Matuska "zfuture": [7, 1000, "zfetch stream future per second"], 1690d4ad640SMartin Matuska "zstride": [7, 1000, "zfetch stream strides per second"], 1700d4ad640SMartin Matuska "zissued": [7, 1000, "zfetch prefetches issued per second"], 1710d4ad640SMartin Matuska "zactive": [7, 1000, "zfetch prefetches active per second"], 172716fd348SMartin Matuska} 173716fd348SMartin Matuska 1747a7741afSMartin Matuska# ARC structural breakdown from arc_summary 1757a7741afSMartin Matuskastructfields = { 1767a7741afSMartin Matuska "cmp": ["compressed", "Compressed"], 1777a7741afSMartin Matuska "ovh": ["overhead", "Overhead"], 1787a7741afSMartin Matuska "bon": ["bonus", "Bonus"], 1797a7741afSMartin Matuska "dno": ["dnode", "Dnode"], 1807a7741afSMartin Matuska "dbu": ["dbuf", "Dbuf"], 1817a7741afSMartin Matuska "hdr": ["hdr", "Header"], 1827a7741afSMartin Matuska "l2h": ["l2_hdr", "L2 header"], 1837a7741afSMartin Matuska "abd": ["abd_chunk_waste", "ABD chunk waste"], 1847a7741afSMartin Matuska} 1857a7741afSMartin Matuskastructstats = { # size stats 1867a7741afSMartin Matuska "percent": "size", # percentage of this value 1877a7741afSMartin Matuska "sz": ["_size", "size"], 1887a7741afSMartin Matuska} 1897a7741afSMartin Matuska 1907a7741afSMartin Matuska# ARC types breakdown from arc_summary 1917a7741afSMartin Matuskatypefields = { 1927a7741afSMartin Matuska "data": ["data", "ARC data"], 1937a7741afSMartin Matuska "meta": ["metadata", "ARC metadata"], 1947a7741afSMartin Matuska} 1957a7741afSMartin Matuskatypestats = { # size stats 1967a7741afSMartin Matuska "percent": "cachessz", # percentage of this value 1977a7741afSMartin Matuska "tg": ["_target", "target"], 1987a7741afSMartin Matuska "sz": ["_size", "size"], 1997a7741afSMartin Matuska} 2007a7741afSMartin Matuska 2017a7741afSMartin Matuska# ARC states breakdown from arc_summary 2027a7741afSMartin Matuskastatefields = { 2037a7741afSMartin Matuska "ano": ["anon", "Anonymous"], 2047a7741afSMartin Matuska "mfu": ["mfu", "MFU"], 2057a7741afSMartin Matuska "mru": ["mru", "MRU"], 2067a7741afSMartin Matuska "unc": ["uncached", "Uncached"], 2077a7741afSMartin Matuska} 2087a7741afSMartin Matuskatargetstats = { 2097a7741afSMartin Matuska "percent": "cachessz", # percentage of this value 2107a7741afSMartin Matuska "fields": ["mfu", "mru"], # only applicable to these fields 2117a7741afSMartin Matuska "tg": ["_target", "target"], 2127a7741afSMartin Matuska "dt": ["_data_target", "data target"], 2137a7741afSMartin Matuska "mt": ["_metadata_target", "metadata target"], 2147a7741afSMartin Matuska} 2157a7741afSMartin Matuskastatestats = { # size stats 2167a7741afSMartin Matuska "percent": "cachessz", # percentage of this value 2177a7741afSMartin Matuska "sz": ["_size", "size"], 2187a7741afSMartin Matuska "da": ["_data", "data size"], 2197a7741afSMartin Matuska "me": ["_metadata", "metadata size"], 2207a7741afSMartin Matuska "ed": ["_evictable_data", "evictable data size"], 2217a7741afSMartin Matuska "em": ["_evictable_metadata", "evictable metadata size"], 2227a7741afSMartin Matuska} 2237a7741afSMartin Matuskaghoststats = { 2247a7741afSMartin Matuska "fields": ["mfu", "mru"], # only applicable to these fields 2257a7741afSMartin Matuska "gsz": ["_ghost_size", "ghost size"], 2267a7741afSMartin Matuska "gd": ["_ghost_data", "ghost data size"], 2277a7741afSMartin Matuska "gm": ["_ghost_metadata", "ghost metadata size"], 2287a7741afSMartin Matuska} 2297a7741afSMartin Matuska 2307a7741afSMartin Matuska# fields and stats 2317a7741afSMartin Matuskafieldstats = [ 2327a7741afSMartin Matuska [structfields, structstats], 2337a7741afSMartin Matuska [typefields, typestats], 2347a7741afSMartin Matuska [statefields, targetstats, statestats, ghoststats], 2357a7741afSMartin Matuska] 2367a7741afSMartin Matuskafor fs in fieldstats: 2377a7741afSMartin Matuska fields, stats = fs[0], fs[1:] 2387a7741afSMartin Matuska for field, fieldval in fields.items(): 2397a7741afSMartin Matuska for group in stats: 2407a7741afSMartin Matuska for stat, statval in group.items(): 2417a7741afSMartin Matuska if stat in ["fields", "percent"] or \ 2427a7741afSMartin Matuska ("fields" in group and field not in group["fields"]): 2437a7741afSMartin Matuska continue 2447a7741afSMartin Matuska colname = field + stat 2457a7741afSMartin Matuska coldesc = fieldval[1] + " " + statval[1] 2467a7741afSMartin Matuska cols[colname] = [len(colname), 1024, coldesc] 2477a7741afSMartin Matuska if "percent" in group: 2487a7741afSMartin Matuska cols[colname + "%"] = [len(colname) + 1, 100, \ 2497a7741afSMartin Matuska coldesc + " percentage"] 2507a7741afSMartin Matuska 251716fd348SMartin Matuskav = {} 25215f0b8c3SMartin Matuskahdr = ["time", "read", "ddread", "ddh%", "dmread", "dmh%", "pread", "ph%", 25315f0b8c3SMartin Matuska "size", "c", "avail"] 25415f0b8c3SMartin Matuskaxhdr = ["time", "mfu", "mru", "mfug", "mrug", "unc", "eskip", "mtxmis", 25515f0b8c3SMartin Matuska "dread", "pread", "read"] 2560d4ad640SMartin Matuskazhdr = ["time", "ztotal", "zhits", "zahead", "zpast", "zmisses", "zmax", 2570d4ad640SMartin Matuska "zfuture", "zstride", "zissued", "zactive"] 258716fd348SMartin Matuskasint = 1 # Default interval is 1 second 259716fd348SMartin Matuskacount = 1 # Default count is 1 260716fd348SMartin Matuskahdr_intr = 20 # Print header every 20 lines of output 261716fd348SMartin Matuskaopfile = None 262716fd348SMartin Matuskasep = " " # Default separator is 2 spaces 263716fd348SMartin Matuskal2exist = False 264716fd348SMartin Matuskacmd = ("Usage: arcstat [-havxp] [-f fields] [-o file] [-s string] [interval " 265716fd348SMartin Matuska "[count]]\n") 266716fd348SMartin Matuskacur = {} 267716fd348SMartin Matuskad = {} 268716fd348SMartin Matuskaout = None 269716fd348SMartin Matuskakstat = None 270716fd348SMartin Matuskapretty_print = True 271716fd348SMartin Matuska 272716fd348SMartin Matuska 273716fd348SMartin Matuskaif sys.platform.startswith('freebsd'): 274716fd348SMartin Matuska # Requires py-sysctl on FreeBSD 275716fd348SMartin Matuska import sysctl 276716fd348SMartin Matuska 277716fd348SMartin Matuska def kstat_update(): 278716fd348SMartin Matuska global kstat 279716fd348SMartin Matuska 280716fd348SMartin Matuska k = [ctl for ctl in sysctl.filter('kstat.zfs.misc.arcstats') 281716fd348SMartin Matuska if ctl.type != sysctl.CTLTYPE_NODE] 282b985c9caSMartin Matuska k += [ctl for ctl in sysctl.filter('kstat.zfs.misc.zfetchstats') 283b985c9caSMartin Matuska if ctl.type != sysctl.CTLTYPE_NODE] 284716fd348SMartin Matuska 285716fd348SMartin Matuska if not k: 286716fd348SMartin Matuska sys.exit(1) 287716fd348SMartin Matuska 288716fd348SMartin Matuska kstat = {} 289716fd348SMartin Matuska 290716fd348SMartin Matuska for s in k: 291716fd348SMartin Matuska if not s: 292716fd348SMartin Matuska continue 293716fd348SMartin Matuska 294716fd348SMartin Matuska name, value = s.name, s.value 295b985c9caSMartin Matuska 296b985c9caSMartin Matuska if "arcstats" in name: 297716fd348SMartin Matuska # Trims 'kstat.zfs.misc.arcstats' from the name 298716fd348SMartin Matuska kstat[name[24:]] = int(value) 299b985c9caSMartin Matuska else: 300b985c9caSMartin Matuska kstat["zfetch_" + name[27:]] = int(value) 301716fd348SMartin Matuska 302716fd348SMartin Matuskaelif sys.platform.startswith('linux'): 303716fd348SMartin Matuska def kstat_update(): 304716fd348SMartin Matuska global kstat 305716fd348SMartin Matuska 3060d4ad640SMartin Matuska k1 = [line.strip() for line in open('/proc/spl/kstat/zfs/arcstats')] 307716fd348SMartin Matuska 3080d4ad640SMartin Matuska k2 = ["zfetch_" + line.strip() for line in 3090d4ad640SMartin Matuska open('/proc/spl/kstat/zfs/zfetchstats')] 3100d4ad640SMartin Matuska 3110d4ad640SMartin Matuska if k1 is None or k2 is None: 312716fd348SMartin Matuska sys.exit(1) 313716fd348SMartin Matuska 3140d4ad640SMartin Matuska del k1[0:2] 3150d4ad640SMartin Matuska del k2[0:2] 3160d4ad640SMartin Matuska k = k1 + k2 317716fd348SMartin Matuska kstat = {} 318716fd348SMartin Matuska 319716fd348SMartin Matuska for s in k: 320716fd348SMartin Matuska if not s: 321716fd348SMartin Matuska continue 322716fd348SMartin Matuska 323716fd348SMartin Matuska name, unused, value = s.split() 324716fd348SMartin Matuska kstat[name] = int(value) 325716fd348SMartin Matuska 326716fd348SMartin Matuska 327716fd348SMartin Matuskadef detailed_usage(): 328716fd348SMartin Matuska sys.stderr.write("%s\n" % cmd) 329716fd348SMartin Matuska sys.stderr.write("Field definitions are as follows:\n") 330716fd348SMartin Matuska for key in cols: 331716fd348SMartin Matuska sys.stderr.write("%11s : %s\n" % (key, cols[key][2])) 332716fd348SMartin Matuska sys.stderr.write("\n") 333716fd348SMartin Matuska 334716fd348SMartin Matuska sys.exit(0) 335716fd348SMartin Matuska 336716fd348SMartin Matuska 337716fd348SMartin Matuskadef usage(): 338716fd348SMartin Matuska sys.stderr.write("%s\n" % cmd) 339716fd348SMartin Matuska sys.stderr.write("\t -h : Print this help message\n") 340716fd348SMartin Matuska sys.stderr.write("\t -a : Print all possible stats\n") 341716fd348SMartin Matuska sys.stderr.write("\t -v : List all possible field headers and definitions" 342716fd348SMartin Matuska "\n") 343716fd348SMartin Matuska sys.stderr.write("\t -x : Print extended stats\n") 3440d4ad640SMartin Matuska sys.stderr.write("\t -z : Print zfetch stats\n") 345716fd348SMartin Matuska sys.stderr.write("\t -f : Specify specific fields to print (see -v)\n") 346716fd348SMartin Matuska sys.stderr.write("\t -o : Redirect output to the specified file\n") 347716fd348SMartin Matuska sys.stderr.write("\t -s : Override default field separator with custom " 348716fd348SMartin Matuska "character or string\n") 349716fd348SMartin Matuska sys.stderr.write("\t -p : Disable auto-scaling of numerical fields\n") 350716fd348SMartin Matuska sys.stderr.write("\nExamples:\n") 351716fd348SMartin Matuska sys.stderr.write("\tarcstat -o /tmp/a.log 2 10\n") 352716fd348SMartin Matuska sys.stderr.write("\tarcstat -s \",\" -o /tmp/a.log 2 10\n") 353716fd348SMartin Matuska sys.stderr.write("\tarcstat -v\n") 354716fd348SMartin Matuska sys.stderr.write("\tarcstat -f time,hit%,dh%,ph%,mh% 1\n") 355716fd348SMartin Matuska sys.stderr.write("\n") 356716fd348SMartin Matuska 357716fd348SMartin Matuska sys.exit(1) 358716fd348SMartin Matuska 359716fd348SMartin Matuska 360716fd348SMartin Matuskadef snap_stats(): 361716fd348SMartin Matuska global cur 362716fd348SMartin Matuska global kstat 363716fd348SMartin Matuska 364716fd348SMartin Matuska prev = copy.deepcopy(cur) 365716fd348SMartin Matuska kstat_update() 366716fd348SMartin Matuska 367716fd348SMartin Matuska cur = kstat 3687a7741afSMartin Matuska 3697a7741afSMartin Matuska # fill in additional values from arc_summary 3707a7741afSMartin Matuska cur["caches_size"] = caches_size = cur["anon_data"]+cur["anon_metadata"]+\ 3717a7741afSMartin Matuska cur["mfu_data"]+cur["mfu_metadata"]+cur["mru_data"]+cur["mru_metadata"]+\ 3727a7741afSMartin Matuska cur["uncached_data"]+cur["uncached_metadata"] 3737a7741afSMartin Matuska s = 4294967296 3747a7741afSMartin Matuska pd = cur["pd"] 3757a7741afSMartin Matuska pm = cur["pm"] 3767a7741afSMartin Matuska meta = cur["meta"] 3777a7741afSMartin Matuska v = (s-int(pd))*(s-int(meta))/s 3787a7741afSMartin Matuska cur["mfu_data_target"] = v / 65536 * caches_size / 65536 3797a7741afSMartin Matuska v = (s-int(pm))*int(meta)/s 3807a7741afSMartin Matuska cur["mfu_metadata_target"] = v / 65536 * caches_size / 65536 3817a7741afSMartin Matuska v = int(pd)*(s-int(meta))/s 3827a7741afSMartin Matuska cur["mru_data_target"] = v / 65536 * caches_size / 65536 3837a7741afSMartin Matuska v = int(pm)*int(meta)/s 3847a7741afSMartin Matuska cur["mru_metadata_target"] = v / 65536 * caches_size / 65536 3857a7741afSMartin Matuska 3867a7741afSMartin Matuska cur["data_target"] = cur["mfu_data_target"] + cur["mru_data_target"] 3877a7741afSMartin Matuska cur["metadata_target"] = cur["mfu_metadata_target"] + cur["mru_metadata_target"] 3887a7741afSMartin Matuska cur["mfu_target"] = cur["mfu_data_target"] + cur["mfu_metadata_target"] 3897a7741afSMartin Matuska cur["mru_target"] = cur["mru_data_target"] + cur["mru_metadata_target"] 3907a7741afSMartin Matuska 391716fd348SMartin Matuska for key in cur: 392716fd348SMartin Matuska if re.match(key, "class"): 393716fd348SMartin Matuska continue 394716fd348SMartin Matuska if key in prev: 395716fd348SMartin Matuska d[key] = cur[key] - prev[key] 396716fd348SMartin Matuska else: 397716fd348SMartin Matuska d[key] = cur[key] 398716fd348SMartin Matuska 399716fd348SMartin Matuska 4007a7741afSMartin Matuskadef isint(num): 4017a7741afSMartin Matuska if isinstance(num, float): 4027a7741afSMartin Matuska return num.is_integer() 4037a7741afSMartin Matuska if isinstance(num, int): 4047a7741afSMartin Matuska return True 4057a7741afSMartin Matuska return False 4067a7741afSMartin Matuska 4077a7741afSMartin Matuska 408716fd348SMartin Matuskadef prettynum(sz, scale, num=0): 409716fd348SMartin Matuska suffix = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z'] 410716fd348SMartin Matuska index = 0 411716fd348SMartin Matuska 412716fd348SMartin Matuska # Special case for date field 413716fd348SMartin Matuska if scale == -1: 414716fd348SMartin Matuska return "%s" % num 415716fd348SMartin Matuska 4167a7741afSMartin Matuska if scale != 100: 417716fd348SMartin Matuska while abs(num) > scale and index < 5: 418716fd348SMartin Matuska num = num / scale 419716fd348SMartin Matuska index += 1 420716fd348SMartin Matuska 4217a7741afSMartin Matuska width = sz - (0 if index == 0 else 1) 4227a7741afSMartin Matuska intlen = len("%.0f" % num) # %.0f rounds to nearest int 4237a7741afSMartin Matuska if sint == 1 and isint(num) or width < intlen + 2: 4247a7741afSMartin Matuska decimal = 0 425716fd348SMartin Matuska else: 4267a7741afSMartin Matuska decimal = 1 4277a7741afSMartin Matuska return "%*.*f%s" % (width, decimal, num, suffix[index]) 428716fd348SMartin Matuska 429716fd348SMartin Matuska 430716fd348SMartin Matuskadef print_values(): 431716fd348SMartin Matuska global hdr 432716fd348SMartin Matuska global sep 433716fd348SMartin Matuska global v 434716fd348SMartin Matuska global pretty_print 435716fd348SMartin Matuska 436716fd348SMartin Matuska if pretty_print: 437716fd348SMartin Matuska fmt = lambda col: prettynum(cols[col][0], cols[col][1], v[col]) 438716fd348SMartin Matuska else: 43908aba0aeSMartin Matuska fmt = lambda col: str(v[col]) 440716fd348SMartin Matuska 441716fd348SMartin Matuska sys.stdout.write(sep.join(fmt(col) for col in hdr)) 442716fd348SMartin Matuska sys.stdout.write("\n") 443716fd348SMartin Matuska sys.stdout.flush() 444716fd348SMartin Matuska 445716fd348SMartin Matuska 446716fd348SMartin Matuskadef print_header(): 447716fd348SMartin Matuska global hdr 448716fd348SMartin Matuska global sep 449716fd348SMartin Matuska global pretty_print 450716fd348SMartin Matuska 451716fd348SMartin Matuska if pretty_print: 452716fd348SMartin Matuska fmt = lambda col: "%*s" % (cols[col][0], col) 453716fd348SMartin Matuska else: 454716fd348SMartin Matuska fmt = lambda col: col 455716fd348SMartin Matuska 456716fd348SMartin Matuska sys.stdout.write(sep.join(fmt(col) for col in hdr)) 457716fd348SMartin Matuska sys.stdout.write("\n") 458716fd348SMartin Matuska 459716fd348SMartin Matuska 460716fd348SMartin Matuskadef get_terminal_lines(): 461716fd348SMartin Matuska try: 462716fd348SMartin Matuska import fcntl 463716fd348SMartin Matuska import termios 464716fd348SMartin Matuska import struct 465716fd348SMartin Matuska data = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, '1234') 466716fd348SMartin Matuska sz = struct.unpack('hh', data) 467716fd348SMartin Matuska return sz[0] 468716fd348SMartin Matuska except Exception: 469716fd348SMartin Matuska pass 470716fd348SMartin Matuska 471716fd348SMartin Matuska 472716fd348SMartin Matuskadef update_hdr_intr(): 473716fd348SMartin Matuska global hdr_intr 474716fd348SMartin Matuska 475716fd348SMartin Matuska lines = get_terminal_lines() 476716fd348SMartin Matuska if lines and lines > 3: 477716fd348SMartin Matuska hdr_intr = lines - 3 478716fd348SMartin Matuska 479716fd348SMartin Matuska 480716fd348SMartin Matuskadef resize_handler(signum, frame): 481716fd348SMartin Matuska update_hdr_intr() 482716fd348SMartin Matuska 483716fd348SMartin Matuska 484716fd348SMartin Matuskadef init(): 485716fd348SMartin Matuska global sint 486716fd348SMartin Matuska global count 487716fd348SMartin Matuska global hdr 488716fd348SMartin Matuska global xhdr 4890d4ad640SMartin Matuska global zhdr 490716fd348SMartin Matuska global opfile 491716fd348SMartin Matuska global sep 492716fd348SMartin Matuska global out 493716fd348SMartin Matuska global l2exist 494716fd348SMartin Matuska global pretty_print 495716fd348SMartin Matuska 496716fd348SMartin Matuska desired_cols = None 497716fd348SMartin Matuska aflag = False 498716fd348SMartin Matuska xflag = False 499716fd348SMartin Matuska hflag = False 500716fd348SMartin Matuska vflag = False 5010d4ad640SMartin Matuska zflag = False 502716fd348SMartin Matuska i = 1 503716fd348SMartin Matuska 504716fd348SMartin Matuska try: 505716fd348SMartin Matuska opts, args = getopt.getopt( 506716fd348SMartin Matuska sys.argv[1:], 5070d4ad640SMartin Matuska "axzo:hvs:f:p", 508716fd348SMartin Matuska [ 509716fd348SMartin Matuska "all", 510716fd348SMartin Matuska "extended", 5110d4ad640SMartin Matuska "zfetch", 512716fd348SMartin Matuska "outfile", 513716fd348SMartin Matuska "help", 514716fd348SMartin Matuska "verbose", 515716fd348SMartin Matuska "separator", 516716fd348SMartin Matuska "columns", 517716fd348SMartin Matuska "parsable" 518716fd348SMartin Matuska ] 519716fd348SMartin Matuska ) 520716fd348SMartin Matuska except getopt.error as msg: 521716fd348SMartin Matuska sys.stderr.write("Error: %s\n" % str(msg)) 522716fd348SMartin Matuska usage() 523716fd348SMartin Matuska opts = None 524716fd348SMartin Matuska 525716fd348SMartin Matuska for opt, arg in opts: 526716fd348SMartin Matuska if opt in ('-a', '--all'): 527716fd348SMartin Matuska aflag = True 528716fd348SMartin Matuska if opt in ('-x', '--extended'): 529716fd348SMartin Matuska xflag = True 530716fd348SMartin Matuska if opt in ('-o', '--outfile'): 531716fd348SMartin Matuska opfile = arg 532716fd348SMartin Matuska i += 1 533716fd348SMartin Matuska if opt in ('-h', '--help'): 534716fd348SMartin Matuska hflag = True 535716fd348SMartin Matuska if opt in ('-v', '--verbose'): 536716fd348SMartin Matuska vflag = True 537716fd348SMartin Matuska if opt in ('-s', '--separator'): 538716fd348SMartin Matuska sep = arg 539716fd348SMartin Matuska i += 1 540716fd348SMartin Matuska if opt in ('-f', '--columns'): 541716fd348SMartin Matuska desired_cols = arg 542716fd348SMartin Matuska i += 1 543716fd348SMartin Matuska if opt in ('-p', '--parsable'): 544716fd348SMartin Matuska pretty_print = False 5450d4ad640SMartin Matuska if opt in ('-z', '--zfetch'): 5460d4ad640SMartin Matuska zflag = True 547716fd348SMartin Matuska i += 1 548716fd348SMartin Matuska 549716fd348SMartin Matuska argv = sys.argv[i:] 550716fd348SMartin Matuska sint = int(argv[0]) if argv else sint 551716fd348SMartin Matuska count = int(argv[1]) if len(argv) > 1 else (0 if len(argv) > 0 else 1) 552716fd348SMartin Matuska 5530d4ad640SMartin Matuska if hflag or (xflag and zflag) or ((zflag or xflag) and desired_cols): 554716fd348SMartin Matuska usage() 555716fd348SMartin Matuska 556716fd348SMartin Matuska if vflag: 557716fd348SMartin Matuska detailed_usage() 558716fd348SMartin Matuska 559716fd348SMartin Matuska if xflag: 560716fd348SMartin Matuska hdr = xhdr 561716fd348SMartin Matuska 5620d4ad640SMartin Matuska if zflag: 5630d4ad640SMartin Matuska hdr = zhdr 5640d4ad640SMartin Matuska 565716fd348SMartin Matuska update_hdr_intr() 566716fd348SMartin Matuska 567716fd348SMartin Matuska # check if L2ARC exists 568716fd348SMartin Matuska snap_stats() 569716fd348SMartin Matuska l2_size = cur.get("l2_size") 570716fd348SMartin Matuska if l2_size: 571716fd348SMartin Matuska l2exist = True 572716fd348SMartin Matuska 573716fd348SMartin Matuska if desired_cols: 574716fd348SMartin Matuska hdr = desired_cols.split(",") 575716fd348SMartin Matuska 576716fd348SMartin Matuska invalid = [] 577716fd348SMartin Matuska incompat = [] 578716fd348SMartin Matuska for ele in hdr: 579716fd348SMartin Matuska if ele not in cols: 580716fd348SMartin Matuska invalid.append(ele) 581716fd348SMartin Matuska elif not l2exist and ele.startswith("l2"): 582716fd348SMartin Matuska sys.stdout.write("No L2ARC Here\n%s\n" % ele) 583716fd348SMartin Matuska incompat.append(ele) 584716fd348SMartin Matuska 585716fd348SMartin Matuska if len(invalid) > 0: 586716fd348SMartin Matuska sys.stderr.write("Invalid column definition! -- %s\n" % invalid) 587716fd348SMartin Matuska usage() 588716fd348SMartin Matuska 589716fd348SMartin Matuska if len(incompat) > 0: 590716fd348SMartin Matuska sys.stderr.write("Incompatible field specified! -- %s\n" % 591716fd348SMartin Matuska incompat) 592716fd348SMartin Matuska usage() 593716fd348SMartin Matuska 594716fd348SMartin Matuska if aflag: 595716fd348SMartin Matuska if l2exist: 596716fd348SMartin Matuska hdr = cols.keys() 597716fd348SMartin Matuska else: 598716fd348SMartin Matuska hdr = [col for col in cols.keys() if not col.startswith("l2")] 599716fd348SMartin Matuska 600716fd348SMartin Matuska if opfile: 601716fd348SMartin Matuska try: 602716fd348SMartin Matuska out = open(opfile, "w") 603716fd348SMartin Matuska sys.stdout = out 604716fd348SMartin Matuska 605716fd348SMartin Matuska except IOError: 606716fd348SMartin Matuska sys.stderr.write("Cannot open %s for writing\n" % opfile) 607716fd348SMartin Matuska sys.exit(1) 608716fd348SMartin Matuska 609716fd348SMartin Matuska 610716fd348SMartin Matuskadef calculate(): 611716fd348SMartin Matuska global d 612716fd348SMartin Matuska global v 613716fd348SMartin Matuska global l2exist 614716fd348SMartin Matuska 615716fd348SMartin Matuska v = dict() 616716fd348SMartin Matuska v["time"] = time.strftime("%H:%M:%S", time.localtime()) 6177a7741afSMartin Matuska v["hits"] = d["hits"] / sint 6187a7741afSMartin Matuska v["iohs"] = d["iohits"] / sint 6197a7741afSMartin Matuska v["miss"] = d["misses"] / sint 62015f0b8c3SMartin Matuska v["read"] = v["hits"] + v["iohs"] + v["miss"] 6217a7741afSMartin Matuska v["hit%"] = 100 * v["hits"] / v["read"] if v["read"] > 0 else 0 6227a7741afSMartin Matuska v["ioh%"] = 100 * v["iohs"] / v["read"] if v["read"] > 0 else 0 62315f0b8c3SMartin Matuska v["miss%"] = 100 - v["hit%"] - v["ioh%"] if v["read"] > 0 else 0 624716fd348SMartin Matuska 6257a7741afSMartin Matuska v["dhit"] = (d["demand_data_hits"] + d["demand_metadata_hits"]) / sint 6267a7741afSMartin Matuska v["dioh"] = (d["demand_data_iohits"] + d["demand_metadata_iohits"]) / sint 6277a7741afSMartin Matuska v["dmis"] = (d["demand_data_misses"] + d["demand_metadata_misses"]) / sint 628716fd348SMartin Matuska 62915f0b8c3SMartin Matuska v["dread"] = v["dhit"] + v["dioh"] + v["dmis"] 6307a7741afSMartin Matuska v["dh%"] = 100 * v["dhit"] / v["dread"] if v["dread"] > 0 else 0 6317a7741afSMartin Matuska v["di%"] = 100 * v["dioh"] / v["dread"] if v["dread"] > 0 else 0 63215f0b8c3SMartin Matuska v["dm%"] = 100 - v["dh%"] - v["di%"] if v["dread"] > 0 else 0 63315f0b8c3SMartin Matuska 6347a7741afSMartin Matuska v["ddhit"] = d["demand_data_hits"] / sint 6357a7741afSMartin Matuska v["ddioh"] = d["demand_data_iohits"] / sint 6367a7741afSMartin Matuska v["ddmis"] = d["demand_data_misses"] / sint 63715f0b8c3SMartin Matuska 63815f0b8c3SMartin Matuska v["ddread"] = v["ddhit"] + v["ddioh"] + v["ddmis"] 6397a7741afSMartin Matuska v["ddh%"] = 100 * v["ddhit"] / v["ddread"] if v["ddread"] > 0 else 0 6407a7741afSMartin Matuska v["ddi%"] = 100 * v["ddioh"] / v["ddread"] if v["ddread"] > 0 else 0 64115f0b8c3SMartin Matuska v["ddm%"] = 100 - v["ddh%"] - v["ddi%"] if v["ddread"] > 0 else 0 64215f0b8c3SMartin Matuska 6437a7741afSMartin Matuska v["dmhit"] = d["demand_metadata_hits"] / sint 6447a7741afSMartin Matuska v["dmioh"] = d["demand_metadata_iohits"] / sint 6457a7741afSMartin Matuska v["dmmis"] = d["demand_metadata_misses"] / sint 64615f0b8c3SMartin Matuska 64715f0b8c3SMartin Matuska v["dmread"] = v["dmhit"] + v["dmioh"] + v["dmmis"] 6487a7741afSMartin Matuska v["dmh%"] = 100 * v["dmhit"] / v["dmread"] if v["dmread"] > 0 else 0 6497a7741afSMartin Matuska v["dmi%"] = 100 * v["dmioh"] / v["dmread"] if v["dmread"] > 0 else 0 65015f0b8c3SMartin Matuska v["dmm%"] = 100 - v["dmh%"] - v["dmi%"] if v["dmread"] > 0 else 0 651716fd348SMartin Matuska 6527a7741afSMartin Matuska v["phit"] = (d["prefetch_data_hits"] + d["prefetch_metadata_hits"]) / sint 65315f0b8c3SMartin Matuska v["pioh"] = (d["prefetch_data_iohits"] + 6547a7741afSMartin Matuska d["prefetch_metadata_iohits"]) / sint 655716fd348SMartin Matuska v["pmis"] = (d["prefetch_data_misses"] + 6567a7741afSMartin Matuska d["prefetch_metadata_misses"]) / sint 657716fd348SMartin Matuska 65815f0b8c3SMartin Matuska v["pread"] = v["phit"] + v["pioh"] + v["pmis"] 6597a7741afSMartin Matuska v["ph%"] = 100 * v["phit"] / v["pread"] if v["pread"] > 0 else 0 6607a7741afSMartin Matuska v["pi%"] = 100 * v["pioh"] / v["pread"] if v["pread"] > 0 else 0 66115f0b8c3SMartin Matuska v["pm%"] = 100 - v["ph%"] - v["pi%"] if v["pread"] > 0 else 0 66215f0b8c3SMartin Matuska 6637a7741afSMartin Matuska v["pdhit"] = d["prefetch_data_hits"] / sint 6647a7741afSMartin Matuska v["pdioh"] = d["prefetch_data_iohits"] / sint 6657a7741afSMartin Matuska v["pdmis"] = d["prefetch_data_misses"] / sint 66615f0b8c3SMartin Matuska 66715f0b8c3SMartin Matuska v["pdread"] = v["pdhit"] + v["pdioh"] + v["pdmis"] 6687a7741afSMartin Matuska v["pdh%"] = 100 * v["pdhit"] / v["pdread"] if v["pdread"] > 0 else 0 6697a7741afSMartin Matuska v["pdi%"] = 100 * v["pdioh"] / v["pdread"] if v["pdread"] > 0 else 0 67015f0b8c3SMartin Matuska v["pdm%"] = 100 - v["pdh%"] - v["pdi%"] if v["pdread"] > 0 else 0 67115f0b8c3SMartin Matuska 6727a7741afSMartin Matuska v["pmhit"] = d["prefetch_metadata_hits"] / sint 6737a7741afSMartin Matuska v["pmioh"] = d["prefetch_metadata_iohits"] / sint 6747a7741afSMartin Matuska v["pmmis"] = d["prefetch_metadata_misses"] / sint 67515f0b8c3SMartin Matuska 67615f0b8c3SMartin Matuska v["pmread"] = v["pmhit"] + v["pmioh"] + v["pmmis"] 6777a7741afSMartin Matuska v["pmh%"] = 100 * v["pmhit"] / v["pmread"] if v["pmread"] > 0 else 0 6787a7741afSMartin Matuska v["pmi%"] = 100 * v["pmioh"] / v["pmread"] if v["pmread"] > 0 else 0 67915f0b8c3SMartin Matuska v["pmm%"] = 100 - v["pmh%"] - v["pmi%"] if v["pmread"] > 0 else 0 680716fd348SMartin Matuska 681716fd348SMartin Matuska v["mhit"] = (d["prefetch_metadata_hits"] + 6827a7741afSMartin Matuska d["demand_metadata_hits"]) / sint 68315f0b8c3SMartin Matuska v["mioh"] = (d["prefetch_metadata_iohits"] + 6847a7741afSMartin Matuska d["demand_metadata_iohits"]) / sint 685716fd348SMartin Matuska v["mmis"] = (d["prefetch_metadata_misses"] + 6867a7741afSMartin Matuska d["demand_metadata_misses"]) / sint 687716fd348SMartin Matuska 68815f0b8c3SMartin Matuska v["mread"] = v["mhit"] + v["mioh"] + v["mmis"] 6897a7741afSMartin Matuska v["mh%"] = 100 * v["mhit"] / v["mread"] if v["mread"] > 0 else 0 6907a7741afSMartin Matuska v["mi%"] = 100 * v["mioh"] / v["mread"] if v["mread"] > 0 else 0 69115f0b8c3SMartin Matuska v["mm%"] = 100 - v["mh%"] - v["mi%"] if v["mread"] > 0 else 0 692716fd348SMartin Matuska 693716fd348SMartin Matuska v["arcsz"] = cur["size"] 694716fd348SMartin Matuska v["size"] = cur["size"] 695716fd348SMartin Matuska v["c"] = cur["c"] 6967a7741afSMartin Matuska v["mfu"] = d["mfu_hits"] / sint 6977a7741afSMartin Matuska v["mru"] = d["mru_hits"] / sint 6987a7741afSMartin Matuska v["mrug"] = d["mru_ghost_hits"] / sint 6997a7741afSMartin Matuska v["mfug"] = d["mfu_ghost_hits"] / sint 7007a7741afSMartin Matuska v["unc"] = d["uncached_hits"] / sint 7017a7741afSMartin Matuska v["eskip"] = d["evict_skip"] / sint 7027a7741afSMartin Matuska v["el2skip"] = d["evict_l2_skip"] / sint 7037a7741afSMartin Matuska v["el2cach"] = d["evict_l2_cached"] / sint 7047a7741afSMartin Matuska v["el2el"] = d["evict_l2_eligible"] / sint 7057a7741afSMartin Matuska v["el2mfu"] = d["evict_l2_eligible_mfu"] / sint 7067a7741afSMartin Matuska v["el2mru"] = d["evict_l2_eligible_mru"] / sint 7077a7741afSMartin Matuska v["el2inel"] = d["evict_l2_ineligible"] / sint 7087a7741afSMartin Matuska v["mtxmis"] = d["mutex_miss"] / sint 7090d4ad640SMartin Matuska v["ztotal"] = (d["zfetch_hits"] + d["zfetch_future"] + d["zfetch_stride"] + 7107a7741afSMartin Matuska d["zfetch_past"] + d["zfetch_misses"]) / sint 7117a7741afSMartin Matuska v["zhits"] = d["zfetch_hits"] / sint 7127a7741afSMartin Matuska v["zahead"] = (d["zfetch_future"] + d["zfetch_stride"]) / sint 7137a7741afSMartin Matuska v["zpast"] = d["zfetch_past"] / sint 7147a7741afSMartin Matuska v["zmisses"] = d["zfetch_misses"] / sint 7157a7741afSMartin Matuska v["zmax"] = d["zfetch_max_streams"] / sint 7167a7741afSMartin Matuska v["zfuture"] = d["zfetch_future"] / sint 7177a7741afSMartin Matuska v["zstride"] = d["zfetch_stride"] / sint 7187a7741afSMartin Matuska v["zissued"] = d["zfetch_io_issued"] / sint 7197a7741afSMartin Matuska v["zactive"] = d["zfetch_io_active"] / sint 7207a7741afSMartin Matuska 7217a7741afSMartin Matuska # ARC structural breakdown, ARC types breakdown, ARC states breakdown 7227a7741afSMartin Matuska v["cachessz"] = cur["caches_size"] 7237a7741afSMartin Matuska for fs in fieldstats: 7247a7741afSMartin Matuska fields, stats = fs[0], fs[1:] 7257a7741afSMartin Matuska for field, fieldval in fields.items(): 7267a7741afSMartin Matuska for group in stats: 7277a7741afSMartin Matuska for stat, statval in group.items(): 7287a7741afSMartin Matuska if stat in ["fields", "percent"] or \ 7297a7741afSMartin Matuska ("fields" in group and field not in group["fields"]): 7307a7741afSMartin Matuska continue 7317a7741afSMartin Matuska colname = field + stat 7327a7741afSMartin Matuska v[colname] = cur[fieldval[0] + statval[0]] 7337a7741afSMartin Matuska if "percent" in group: 7347a7741afSMartin Matuska v[colname + "%"] = 100 * v[colname] / \ 7357a7741afSMartin Matuska v[group["percent"]] if v[group["percent"]] > 0 else 0 736716fd348SMartin Matuska 737716fd348SMartin Matuska if l2exist: 7387a7741afSMartin Matuska v["l2hits"] = d["l2_hits"] / sint 7397a7741afSMartin Matuska v["l2miss"] = d["l2_misses"] / sint 740716fd348SMartin Matuska v["l2read"] = v["l2hits"] + v["l2miss"] 7417a7741afSMartin Matuska v["l2hit%"] = 100 * v["l2hits"] / v["l2read"] if v["l2read"] > 0 else 0 742716fd348SMartin Matuska 743716fd348SMartin Matuska v["l2miss%"] = 100 - v["l2hit%"] if v["l2read"] > 0 else 0 744716fd348SMartin Matuska v["l2asize"] = cur["l2_asize"] 745716fd348SMartin Matuska v["l2size"] = cur["l2_size"] 7467a7741afSMartin Matuska v["l2bytes"] = d["l2_read_bytes"] / sint 7477a7741afSMartin Matuska v["l2wbytes"] = d["l2_write_bytes"] / sint 748716fd348SMartin Matuska 749716fd348SMartin Matuska v["l2pref"] = cur["l2_prefetch_asize"] 750716fd348SMartin Matuska v["l2mfu"] = cur["l2_mfu_asize"] 751716fd348SMartin Matuska v["l2mru"] = cur["l2_mru_asize"] 752716fd348SMartin Matuska v["l2data"] = cur["l2_bufc_data_asize"] 753716fd348SMartin Matuska v["l2meta"] = cur["l2_bufc_metadata_asize"] 7547a7741afSMartin Matuska v["l2pref%"] = 100 * v["l2pref"] / v["l2asize"] 7557a7741afSMartin Matuska v["l2mfu%"] = 100 * v["l2mfu"] / v["l2asize"] 7567a7741afSMartin Matuska v["l2mru%"] = 100 * v["l2mru"] / v["l2asize"] 7577a7741afSMartin Matuska v["l2data%"] = 100 * v["l2data"] / v["l2asize"] 7587a7741afSMartin Matuska v["l2meta%"] = 100 * v["l2meta"] / v["l2asize"] 759716fd348SMartin Matuska 760716fd348SMartin Matuska v["grow"] = 0 if cur["arc_no_grow"] else 1 761716fd348SMartin Matuska v["need"] = cur["arc_need_free"] 762716fd348SMartin Matuska v["free"] = cur["memory_free_bytes"] 763716fd348SMartin Matuska v["avail"] = cur["memory_available_bytes"] 764716fd348SMartin Matuska v["waste"] = cur["abd_chunk_waste_size"] 765716fd348SMartin Matuska 766716fd348SMartin Matuska 767716fd348SMartin Matuskadef main(): 768716fd348SMartin Matuska global sint 769716fd348SMartin Matuska global count 770716fd348SMartin Matuska global hdr_intr 771716fd348SMartin Matuska 772716fd348SMartin Matuska i = 0 773716fd348SMartin Matuska count_flag = 0 774716fd348SMartin Matuska 775716fd348SMartin Matuska init() 776716fd348SMartin Matuska if count > 0: 777716fd348SMartin Matuska count_flag = 1 778716fd348SMartin Matuska 779716fd348SMartin Matuska signal(SIGINT, SIG_DFL) 780716fd348SMartin Matuska signal(SIGWINCH, resize_handler) 781716fd348SMartin Matuska while True: 782716fd348SMartin Matuska if i == 0: 783716fd348SMartin Matuska print_header() 784716fd348SMartin Matuska 785716fd348SMartin Matuska snap_stats() 786716fd348SMartin Matuska calculate() 787716fd348SMartin Matuska print_values() 788716fd348SMartin Matuska 789716fd348SMartin Matuska if count_flag == 1: 790716fd348SMartin Matuska if count <= 1: 791716fd348SMartin Matuska break 792716fd348SMartin Matuska count -= 1 793716fd348SMartin Matuska 794716fd348SMartin Matuska i = 0 if i >= hdr_intr else i + 1 795716fd348SMartin Matuska time.sleep(sint) 796716fd348SMartin Matuska 797716fd348SMartin Matuska if out: 798716fd348SMartin Matuska out.close() 799716fd348SMartin Matuska 800716fd348SMartin Matuska 801716fd348SMartin Matuskaif __name__ == '__main__': 802716fd348SMartin Matuska main() 803