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