linux: implement filesystem-side clone ioctls
[zfs.git] / cmd / arcstat.in
blob8df1c62f7e86b1b06bfa737537fd7336d91f14b6
1 #!/usr/bin/env @PYTHON_SHEBANG@
3 # Print out ZFS ARC Statistics exported via kstat(1)
4 # For a definition of fields, or usage, use arcstat -v
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
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
16 # but has since moved to the illumos-gate repository.
18 # This Python port was written by John Hixson for FreeNAS, introduced
19 # in commit e2c29f:
20 #    https://github.com/freenas/freenas
22 # and has been improved by many people since.
24 # CDDL HEADER START
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.
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.
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]
42 # CDDL HEADER END
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.
50 # This script must remain compatible with Python 3.6+.
53 import sys
54 import time
55 import getopt
56 import re
57 import copy
59 from signal import signal, SIGINT, SIGWINCH, SIG_DFL
62 cols = {
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"],
162 v = {}
163 hdr = ["time", "read", "ddread", "ddh%", "dmread", "dmh%", "pread", "ph%",
164        "size", "c", "avail"]
165 xhdr = ["time", "mfu", "mru", "mfug", "mrug", "unc", "eskip", "mtxmis",
166         "dread", "pread", "read"]
167 sint = 1               # Default interval is 1 second
168 count = 1              # Default count is 1
169 hdr_intr = 20          # Print header every 20 lines of output
170 opfile = None
171 sep = "  "              # Default separator is 2 spaces
172 l2exist = False
173 cmd = ("Usage: arcstat [-havxp] [-f fields] [-o file] [-s string] [interval "
174        "[count]]\n")
175 cur = {}
176 d = {}
177 out = None
178 kstat = None
179 pretty_print = True
182 if sys.platform.startswith('freebsd'):
183     # Requires py-sysctl on FreeBSD
184     import sysctl
186     def kstat_update():
187         global kstat
189         k = [ctl for ctl in sysctl.filter('kstat.zfs.misc.arcstats')
190              if ctl.type != sysctl.CTLTYPE_NODE]
192         if not k:
193             sys.exit(1)
195         kstat = {}
197         for s in k:
198             if not s:
199                 continue
201             name, value = s.name, s.value
202             # Trims 'kstat.zfs.misc.arcstats' from the name
203             kstat[name[24:]] = int(value)
205 elif sys.platform.startswith('linux'):
206     def kstat_update():
207         global kstat
209         k = [line.strip() for line in open('/proc/spl/kstat/zfs/arcstats')]
211         if not k:
212             sys.exit(1)
214         del k[0:2]
215         kstat = {}
217         for s in k:
218             if not s:
219                 continue
221             name, unused, value = s.split()
222             kstat[name] = int(value)
225 def 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")
232     sys.exit(0)
235 def 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")
254     sys.exit(1)
257 def snap_stats():
258     global cur
259     global kstat
261     prev = copy.deepcopy(cur)
262     kstat_update()
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]
274 def prettynum(sz, scale, num=0):
275     suffix = [' ', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']
276     index = 0
277     save = 0
279     # Special case for date field
280     if scale == -1:
281         return "%s" % num
283     # Rounding error, return 0
284     elif 0 < num < 1:
285         num = 0
287     while abs(num) > scale and index < 5:
288         save = num
289         num = num / scale
290         index += 1
292     if index == 0:
293         return "%*d" % (sz, num)
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])
301 def print_values():
302     global hdr
303     global sep
304     global v
305     global pretty_print
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])
312     sys.stdout.write(sep.join(fmt(col) for col in hdr))
313     sys.stdout.write("\n")
314     sys.stdout.flush()
317 def print_header():
318     global hdr
319     global sep
320     global pretty_print
322     if pretty_print:
323         fmt = lambda col: "%*s" % (cols[col][0], col)
324     else:
325         fmt = lambda col: col
327     sys.stdout.write(sep.join(fmt(col) for col in hdr))
328     sys.stdout.write("\n")
331 def 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
343 def update_hdr_intr():
344     global hdr_intr
346     lines = get_terminal_lines()
347     if lines and lines > 3:
348         hdr_intr = lines - 3
351 def resize_handler(signum, frame):
352     update_hdr_intr()
355 def 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
366     desired_cols = None
367     aflag = False
368     xflag = False
369     hflag = False
370     vflag = False
371     i = 1
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
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
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)
419     if hflag or (xflag and desired_cols):
420         usage()
422     if vflag:
423         detailed_usage()
425     if xflag:
426         hdr = xhdr
428     update_hdr_intr()
430     # check if L2ARC exists
431     snap_stats()
432     l2_size = cur.get("l2_size")
433     if l2_size:
434         l2exist = True
436     if desired_cols:
437         hdr = desired_cols.split(",")
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)
448         if len(invalid) > 0:
449             sys.stderr.write("Invalid column definition! -- %s\n" % invalid)
450             usage()
452         if len(incompat) > 0:
453             sys.stderr.write("Incompatible field specified! -- %s\n" %
454                              incompat)
455             usage()
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")]
463     if opfile:
464         try:
465             out = open(opfile, "w")
466             sys.stdout = out
468         except IOError:
469             sys.stderr.write("Cannot open %s for writing\n" % opfile)
470             sys.exit(1)
473 def calculate():
474     global d
475     global v
476     global l2exist
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
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
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
497     v["ddhit"] = d["demand_data_hits"] // sint
498     v["ddioh"] = d["demand_data_iohits"] // sint
499     v["ddmis"] = d["demand_data_misses"] // sint
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
506     v["dmhit"] = d["demand_metadata_hits"] // sint
507     v["dmioh"] = d["demand_metadata_iohits"] // sint
508     v["dmmis"] = d["demand_metadata_misses"] // sint
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
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
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
526     v["pdhit"] = d["prefetch_data_hits"] // sint
527     v["pdioh"] = d["prefetch_data_iohits"] // sint
528     v["pdmis"] = d["prefetch_data_misses"] // sint
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
535     v["pmhit"] = d["prefetch_metadata_hits"] // sint
536     v["pmioh"] = d["prefetch_metadata_iohits"] // sint
537     v["pmmis"] = d["prefetch_metadata_misses"] // sint
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
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
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
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
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
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
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"]
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"]
602 def main():
603     global sint
604     global count
605     global hdr_intr
607     i = 0
608     count_flag = 0
610     init()
611     if count > 0:
612         count_flag = 1
614     signal(SIGINT, SIG_DFL)
615     signal(SIGWINCH, resize_handler)
616     while True:
617         if i == 0:
618             print_header()
620         snap_stats()
621         calculate()
622         print_values()
624         if count_flag == 1:
625             if count <= 1:
626                 break
627             count -= 1
629         i = 0 if i >= hdr_intr else i + 1
630         time.sleep(sint)
632     if out:
633         out.close()
636 if __name__ == '__main__':
637     main()