xref: /freebsd/usr.bin/systat/zarc.c (revision 535af610)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2014 - 2017, 2019 Yoshihiro Ota
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30 
31 #include <sys/types.h>
32 #include <sys/sysctl.h>
33 
34 #include <inttypes.h>
35 #include <string.h>
36 #include <err.h>
37 #include <libutil.h>
38 
39 #include "systat.h"
40 #include "extern.h"
41 #include "devs.h"
42 
43 struct zfield {
44 	uint64_t arcstats;
45 	uint64_t arcstats_demand_data;
46 	uint64_t arcstats_demand_metadata;
47 	uint64_t arcstats_prefetch_data;
48 	uint64_t arcstats_prefetch_metadata;
49 	uint64_t zfetchstats;
50 	uint64_t arcstats_l2;
51 };
52 
53 static struct zarcstats {
54 	struct zfield hits;
55 	struct zfield misses;
56 } curstat, initstat, oldstat;
57 
58 struct zarcrates {
59 	struct zfield current;
60 	struct zfield total;
61 };
62 
63 static void
64 getinfo(struct zarcstats *ls);
65 
66 WINDOW *
67 openzarc(void)
68 {
69 
70 	return (subwin(stdscr, LINES - 3 - 1, 0, MAINWIN_ROW, 0));
71 }
72 
73 void
74 closezarc(WINDOW *w)
75 {
76 
77 	if (w == NULL)
78 		return;
79 	wclear(w);
80 	wrefresh(w);
81 	delwin(w);
82 }
83 
84 void
85 labelzarc(void)
86 {
87 	int row = 1;
88 
89 	wmove(wnd, 0, 0); wclrtoeol(wnd);
90 	mvwprintw(wnd, 0, 31+1, "%4.4s %6.6s %6.6s | Total %4.4s %6.6s %6.6s",
91 		"Rate", "Hits", "Misses", "Rate", "Hits", "Misses");
92 #define L(str) mvwprintw(wnd, row++, 5, \
93 		"%-26.26s:   %%               |          %%", #str)
94 	L(arcstats);
95 	L(arcstats.demand_data);
96 	L(arcstats.demand_metadata);
97 	L(arcstats.prefetch_data);
98 	L(arcstats.prefetch_metadata);
99 	L(zfetchstats);
100 	L(arcstats.l2);
101 #undef L
102 	dslabel(12, 0, 18);
103 }
104 
105 static int
106 calc_rate(uint64_t hits, uint64_t misses)
107 {
108     if(hits)
109 	return 100 * hits / (hits + misses);
110     else
111 	return 0;
112 }
113 
114 static void
115 domode(struct zarcstats *delta, struct zarcrates *rate)
116 {
117 #define DO(stat) \
118 	delta->hits.stat = (curstat.hits.stat - oldstat.hits.stat); \
119 	delta->misses.stat = (curstat.misses.stat - oldstat.misses.stat); \
120 	rate->current.stat = calc_rate(delta->hits.stat, delta->misses.stat); \
121 	rate->total.stat = calc_rate(curstat.hits.stat, curstat.misses.stat)
122 	DO(arcstats);
123 	DO(arcstats_demand_data);
124 	DO(arcstats_demand_metadata);
125 	DO(arcstats_prefetch_data);
126 	DO(arcstats_prefetch_metadata);
127 	DO(zfetchstats);
128 	DO(arcstats_l2);
129 	DO(arcstats);
130 	DO(arcstats_demand_data);
131 	DO(arcstats_demand_metadata);
132 	DO(arcstats_prefetch_data);
133 	DO(arcstats_prefetch_metadata);
134 	DO(zfetchstats);
135 	DO(arcstats_l2);
136 #undef DO
137 }
138 
139 void
140 showzarc(void)
141 {
142 	int row = 1;
143 	struct zarcstats delta = {};
144 	struct zarcrates rate = {};
145 
146 	domode(&delta, &rate);
147 
148 #define DO(stat, col, width) \
149 	sysputuint64(wnd, row, col, width, stat, HN_DIVISOR_1000)
150 #define	RATES(stat) mvwprintw(wnd, row, 31+1, "%3"PRIu64, rate.current.stat);\
151 	mvwprintw(wnd, row, 31+1+5+7+7+8, "%3"PRIu64, rate.total.stat)
152 #define	HITS(stat) DO(delta.hits.stat, 31+1+5, 6); \
153 	DO(curstat.hits.stat, 31+1+5+7+7+8+5, 6)
154 #define	MISSES(stat) DO(delta.misses.stat, 31+1+5+7, 6); \
155 	DO(curstat.misses.stat, 31+1+5+7+7+8+5+7, 6)
156 #define	E(stat) RATES(stat); HITS(stat); MISSES(stat); ++row
157 	E(arcstats);
158 	E(arcstats_demand_data);
159 	E(arcstats_demand_metadata);
160 	E(arcstats_prefetch_data);
161 	E(arcstats_prefetch_metadata);
162 	E(zfetchstats);
163 	E(arcstats_l2);
164 #undef DO
165 #undef E
166 #undef MISSES
167 #undef HITS
168 #undef RATES
169 	dsshow(12, 0, 18, &cur_dev, &last_dev);
170 }
171 
172 int
173 initzarc(void)
174 {
175 	dsinit(12);
176 	getinfo(&initstat);
177 	curstat = oldstat = initstat;
178 
179 	return 1;
180 }
181 
182 void
183 resetzarc(void)
184 {
185 
186 	initzarc();
187 }
188 
189 static void
190 getinfo(struct zarcstats *ls)
191 {
192 	struct devinfo *tmp_dinfo;
193 
194 	tmp_dinfo = last_dev.dinfo;
195 	last_dev.dinfo = cur_dev.dinfo;
196 	cur_dev.dinfo = tmp_dinfo;
197 
198 	last_dev.snap_time = cur_dev.snap_time;
199 	dsgetinfo(&cur_dev);
200 
201 	size_t size = sizeof(ls->hits.arcstats);
202 	if (sysctlbyname("kstat.zfs.misc.arcstats.hits",
203 		&ls->hits.arcstats, &size, NULL, 0) != 0)
204 		return;
205 	GETSYSCTL("kstat.zfs.misc.arcstats.misses",
206 		ls->misses.arcstats);
207 	GETSYSCTL("kstat.zfs.misc.arcstats.demand_data_hits",
208 		ls->hits.arcstats_demand_data);
209 	GETSYSCTL("kstat.zfs.misc.arcstats.demand_data_misses",
210 		ls->misses.arcstats_demand_data);
211 	GETSYSCTL("kstat.zfs.misc.arcstats.demand_metadata_hits",
212 		ls->hits.arcstats_demand_metadata);
213 	GETSYSCTL("kstat.zfs.misc.arcstats.demand_metadata_misses",
214 		ls->misses.arcstats_demand_metadata);
215 	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_data_hits",
216 		ls->hits.arcstats_prefetch_data);
217 	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_data_misses",
218 		ls->misses.arcstats_prefetch_data);
219 	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_metadata_hits",
220 		ls->hits.arcstats_prefetch_metadata);
221 	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_metadata_misses",
222 		ls->misses.arcstats_prefetch_metadata);
223 	GETSYSCTL("kstat.zfs.misc.zfetchstats.hits",
224 		ls->hits.zfetchstats);
225 	GETSYSCTL("kstat.zfs.misc.zfetchstats.misses",
226 		ls->misses.zfetchstats);
227 	GETSYSCTL("kstat.zfs.misc.arcstats.l2_hits",
228 		ls->hits.arcstats_l2);
229 	GETSYSCTL("kstat.zfs.misc.arcstats.l2_misses",
230 		ls->misses.arcstats_l2);
231 }
232 
233 void
234 fetchzarc(void)
235 {
236 
237 	oldstat = curstat;
238 	getinfo(&curstat);
239 }
240