arcstat: add 'avail', fix 'free'

The meaning of the `free` field is currently `zfs_arc_sys_free`, which
is the target amount of memory to leave free for the system, and is
constant after booting.

This commit changes the meaning of `free` to arc_free_memory(), the
amount of memory that the ARC considers to be free.

It also adds a new arcstat field `avail`, which tracks
`arc_available_memory()`.

Since `avail` can be negative, it also updates the arcstat script to
pretty-print negative values.

example output:

  $ arcstat -f time,miss,arcsz,c,grow,need,free,avail 1
      time  miss  arcsz     c  grow  need  free  avail
  15:03:02   39K   114G  114G     0     0  2.4G  407M
  15:03:03   42K   114G  114G     0     0  2.1G  120M
  15:03:04   40K   114G  114G     0     0  1.8G  -177M
  15:03:05   24K   113G  112G     0     0  1.7G  -269M
  15:03:06   29K   111G  110G     0     0  1.6G  -385M
  15:03:07   27K   110G  108G     0     0  1.4G  -535M
  15:03:08   13K   108G  108G     0     0  2.2G  239M
  15:03:09   33K   107G  107G     0     0  1.3G  -639M
  15:03:10   16K   105G  102G     0     0  2.6G  704M
  15:03:11  7.2K   102G  102G     0     0  5.1G  3.1G
  15:03:12   42K   103G  102G     0     0  4.8G  2.8G

Reviewed-by: George Melikov <mail@gmelikov.ru>
Reviewed-by: Pavel Zakharov <pavel.zakharov@delphix.com>
Reviewed-by: Tony Nguyen <tony.nguyen@delphix.com>
Signed-off-by: Matthew Ahrens <mahrens@delphix.com>
Closes #10494
This commit is contained in:
Matthew Ahrens 2020-06-26 18:05:28 -07:00 committed by GitHub
parent bfcbec6f5d
commit 7b232e9354
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 13 deletions

View File

@ -81,6 +81,7 @@ cols = {
"mh%": [3, 100, "Metadata hit percentage"], "mh%": [3, 100, "Metadata hit percentage"],
"mm%": [3, 100, "Metadata miss percentage"], "mm%": [3, 100, "Metadata miss percentage"],
"arcsz": [5, 1024, "ARC size"], "arcsz": [5, 1024, "ARC size"],
"size": [4, 1024, "ARC size"],
"c": [4, 1024, "ARC target size"], "c": [4, 1024, "ARC target size"],
"mfu": [4, 1000, "MFU list hits per second"], "mfu": [4, 1000, "MFU list hits per second"],
"mru": [4, 1000, "MRU list hits per second"], "mru": [4, 1000, "MRU list hits per second"],
@ -101,11 +102,12 @@ cols = {
"grow": [4, 1000, "ARC grow disabled"], "grow": [4, 1000, "ARC grow disabled"],
"need": [4, 1024, "ARC reclaim need"], "need": [4, 1024, "ARC reclaim need"],
"free": [4, 1024, "ARC free memory"], "free": [4, 1024, "ARC free memory"],
"avail": [5, 1024, "ARC available memory"],
} }
v = {} v = {}
hdr = ["time", "read", "miss", "miss%", "dmis", "dm%", "pmis", "pm%", "mmis", hdr = ["time", "read", "miss", "miss%", "dmis", "dm%", "pmis", "pm%", "mmis",
"mm%", "arcsz", "c"] "mm%", "size", "c", "avail"]
xhdr = ["time", "mfu", "mru", "mfug", "mrug", "eskip", "mtxmis", "dread", xhdr = ["time", "mfu", "mru", "mfug", "mrug", "eskip", "mtxmis", "dread",
"pread", "read"] "pread", "read"]
sint = 1 # Default interval is 1 second sint = 1 # Default interval is 1 second
@ -225,7 +227,7 @@ def prettynum(sz, scale, num=0):
elif 0 < num < 1: elif 0 < num < 1:
num = 0 num = 0
while num > scale and index < 5: while abs(num) > scale and index < 5:
save = num save = num
num = num / scale num = num / scale
index += 1 index += 1
@ -233,7 +235,7 @@ def prettynum(sz, scale, num=0):
if index == 0: if index == 0:
return "%*d" % (sz, num) return "%*d" % (sz, num)
if (save / scale) < 10: if abs(save / scale) < 10:
return "%*.1f%s" % (sz - 1, num, suffix[index]) return "%*.1f%s" % (sz - 1, num, suffix[index])
else: else:
return "%*d%s" % (sz - 1, num, suffix[index]) return "%*d%s" % (sz - 1, num, suffix[index])
@ -244,11 +246,9 @@ def print_values():
global sep global sep
global v global v
for col in hdr: sys.stdout.write(sep.join(
sys.stdout.write("%s%s" % ( prettynum(cols[col][0], cols[col][1], v[col]) for col in hdr))
prettynum(cols[col][0], cols[col][1], v[col]),
sep
))
sys.stdout.write("\n") sys.stdout.write("\n")
sys.stdout.flush() sys.stdout.flush()
@ -257,8 +257,8 @@ def print_header():
global hdr global hdr
global sep global sep
for col in hdr: sys.stdout.write(sep.join("%*s" % (cols[col][0], col) for col in hdr))
sys.stdout.write("%*s%s" % (cols[col][0], col, sep))
sys.stdout.write("\n") sys.stdout.write("\n")
@ -428,6 +428,7 @@ def calculate():
v["mm%"] = 100 - v["mh%"] if v["mread"] > 0 else 0 v["mm%"] = 100 - v["mh%"] if v["mread"] > 0 else 0
v["arcsz"] = cur["size"] v["arcsz"] = cur["size"]
v["size"] = cur["size"]
v["c"] = cur["c"] v["c"] = cur["c"]
v["mfu"] = d["mfu_hits"] / sint v["mfu"] = d["mfu_hits"] / sint
v["mru"] = d["mru_hits"] / sint v["mru"] = d["mru_hits"] / sint
@ -449,7 +450,8 @@ def calculate():
v["grow"] = 0 if cur["arc_no_grow"] else 1 v["grow"] = 0 if cur["arc_no_grow"] else 1
v["need"] = cur["arc_need_free"] v["need"] = cur["arc_need_free"]
v["free"] = cur["arc_sys_free"] v["free"] = cur["memory_free_bytes"]
v["avail"] = cur["memory_available_bytes"]
def main(): def main():

View File

@ -236,12 +236,21 @@ Time
.sp .sp
.ne 2 .ne 2
.na .na
\fBarcsz \fR \fBsize \fR
.ad .ad
.RS 14n .RS 14n
ARC size ARC size
.RE .RE
.sp
.ne 2
.na
\fBarcsz \fR
.ad
.RS 14n
Alias for \fBsize\fR
.RE
.sp .sp
.ne 2 .ne 2
.na .na
@ -392,7 +401,18 @@ ARC reclaim needed
\fBfree \fR \fBfree \fR
.ad .ad
.RS 14n .RS 14n
ARC free memory The ARC's idea of how much free memory there is, which includes evictable memory in the page cache.
Since the ARC tries to keep \fBavail\fR above zero, \fBavail\fR is usually more instructive to observe than \fBfree\fR.
.RE
.sp
.ne 2
.na
\fBavail \fR
.ad
.RS 14n
The ARC's idea of how much free memory is available to it, which is a bit less than \fBfree\fR.
May temporarily be negative, in which case the ARC will reduce the target size \fBc\fR.
.RE .RE
.\" .\"