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