xref: /dragonfly/sbin/hammer/cmd_stats.c (revision 71990c18)
1 /*
2  * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * $DragonFly: src/sbin/hammer/cmd_stats.c,v 1.3 2008/07/14 20:28:07 dillon Exp $
35  */
36 
37 #include <sys/sysctl.h>
38 #include <math.h>
39 
40 #include "hammer.h"
41 
42 static void loaddelay(struct timespec *ts, const char *arg);
43 
44 #define _HAMMER "vfs.hammer.stats_"
45 #define bstats_title	\
46 "   lookups   searches    inserts    deletes   elements     splits iterations  rootiters   reciters"
47 #define iostats_title	\
48 "   f_read   f_write   f_iopsr   f_iopsw    d_read   d_write i_flushes   commits      undo      redo"
49 
50 /*
51  * Taken from sys/vfs/hammer/hammer_vfsops.c
52  */
53 struct btree_stats {
54 	int64_t btree_lookups;
55 	int64_t btree_searches;
56 	int64_t btree_inserts;
57 	int64_t btree_deletes;
58 	int64_t btree_elements;
59 	int64_t btree_splits;
60 	int64_t btree_iterations;
61 	int64_t btree_root_iterations;
62 	int64_t record_iterations;
63 };
64 
65 struct io_stats {
66 	int64_t file_read;
67 	int64_t file_write;
68 	int64_t file_iopsr;
69 	int64_t file_iopsw;
70 	int64_t disk_read;
71 	int64_t disk_write;
72 	int64_t inode_flushes;
73 	int64_t commits;
74 	int64_t undo;
75 	int64_t redo;
76 };
77 
78 static __inline __always_inline
79 int
80 _sysctl(const char *name, int64_t *p)
81 {
82 	size_t len = sizeof(*p);
83 	return(sysctlbyname(name, p, &len, NULL, 0));
84 }
85 
86 static __inline __always_inline
87 void
88 collect_bstats(struct btree_stats *p)
89 {
90 	/* sysctls must exist, so ignore return values */
91 	_sysctl(_HAMMER"btree_lookups", &p->btree_lookups);
92 	_sysctl(_HAMMER"btree_searches", &p->btree_searches);
93 	_sysctl(_HAMMER"btree_inserts", &p->btree_inserts);
94 	_sysctl(_HAMMER"btree_deletes", &p->btree_deletes);
95 	_sysctl(_HAMMER"btree_elements", &p->btree_elements);
96 	_sysctl(_HAMMER"btree_splits", &p->btree_splits);
97 	_sysctl(_HAMMER"btree_iterations", &p->btree_iterations);
98 	_sysctl(_HAMMER"btree_root_iterations", &p->btree_root_iterations);
99 	_sysctl(_HAMMER"record_iterations", &p->record_iterations);
100 }
101 
102 static __inline __always_inline
103 void
104 collect_iostats(struct io_stats *p)
105 {
106 	/* sysctls must exist, so ignore return values */
107 	_sysctl(_HAMMER"file_read", &p->file_read);
108 	_sysctl(_HAMMER"file_write", &p->file_write);
109 	_sysctl(_HAMMER"file_iopsr", &p->file_iopsr);
110 	_sysctl(_HAMMER"file_iopsw", &p->file_iopsw);
111 	_sysctl(_HAMMER"disk_read", &p->disk_read);
112 	_sysctl(_HAMMER"disk_write", &p->disk_write);
113 	_sysctl(_HAMMER"inode_flushes", &p->inode_flushes);
114 	_sysctl(_HAMMER"commits", &p->commits);
115 	_sysctl(_HAMMER"undo", &p->undo);
116 	_sysctl(_HAMMER"redo", &p->redo);
117 }
118 
119 static __inline __always_inline
120 void
121 print_bstats(const struct btree_stats *p1, const struct btree_stats *p2)
122 {
123 	printf("%10jd %10jd %10jd %10jd %10jd %10jd %10jd %10jd %10jd",
124 		(intmax_t)(p1->btree_lookups - p2->btree_lookups),
125 		(intmax_t)(p1->btree_searches - p2->btree_searches),
126 		(intmax_t)(p1->btree_inserts - p2->btree_inserts),
127 		(intmax_t)(p1->btree_deletes - p2->btree_deletes),
128 		(intmax_t)(p1->btree_elements - p2->btree_elements),
129 		(intmax_t)(p1->btree_splits - p2->btree_splits),
130 		(intmax_t)(p1->btree_iterations - p2->btree_iterations),
131 		(intmax_t)(p1->btree_root_iterations - p2->btree_root_iterations),
132 		(intmax_t)(p1->record_iterations - p2->record_iterations));
133 		/* no trailing \n */
134 }
135 
136 static __inline __always_inline
137 void
138 print_iostats(const struct io_stats *p1, const struct io_stats *p2)
139 {
140 	printf("%9jd %9jd %9jd %9jd %9jd %9jd %9jd %9jd %9jd %9jd",
141 		(intmax_t)(p1->file_read - p2->file_read),
142 		(intmax_t)(p1->file_write - p2->file_write),
143 		(intmax_t)(p1->file_iopsr - p2->file_iopsr),
144 		(intmax_t)(p1->file_iopsw - p2->file_iopsw),
145 		(intmax_t)(p1->disk_read - p2->disk_read),
146 		(intmax_t)(p1->disk_write - p2->disk_write),
147 		(intmax_t)(p1->inode_flushes - p2->inode_flushes),
148 		(intmax_t)(p1->commits - p2->commits),
149 		(intmax_t)(p1->undo - p2->undo),
150 		(intmax_t)(p1->redo - p2->redo));
151 		/* no trailing \n */
152 }
153 
154 void
155 hammer_cmd_bstats(char **av, int ac)
156 {
157 	struct btree_stats st1, st2;
158 	struct timespec delay = {1, 0};
159 	int count;
160 
161 	bzero(&st1, sizeof(st1));
162 	bzero(&st2, sizeof(st2));
163 
164 	if (ac > 0)
165 		loaddelay(&delay, av[0]);
166 
167 	for (count = 0; ; ++count) {
168 		collect_bstats(&st1);
169 		if (count) {
170 			if ((count & 15) == 1)
171 				printf(bstats_title"\n");
172 			print_bstats(&st1, &st2);
173 			printf("\n");
174 		}
175 		bcopy(&st1, &st2, sizeof(st2));
176 		nanosleep(&delay, NULL);
177 	}
178 }
179 
180 void
181 hammer_cmd_iostats(char **av, int ac)
182 {
183 	struct io_stats st1, st2;
184 	struct timespec delay = {1, 0};
185 	int count;
186 
187 	bzero(&st1, sizeof(st1));
188 	bzero(&st2, sizeof(st2));
189 
190 	if (ac > 0)
191 		loaddelay(&delay, av[0]);
192 
193 	for (count = 0; ; ++count) {
194 		collect_iostats(&st1);
195 		if (count) {
196 			if ((count & 15) == 1)
197 				printf(iostats_title"\n");
198 			print_iostats(&st1, &st2);
199 			printf("\n");
200 		}
201 		bcopy(&st1, &st2, sizeof(st2));
202 		nanosleep(&delay, NULL);
203 	}
204 }
205 
206 void
207 hammer_cmd_stats(char **av, int ac)
208 {
209 	struct btree_stats bst1, bst2;
210 	struct io_stats ist1, ist2;
211 	struct timespec delay = {1, 0};
212 	int count;
213 
214 	bzero(&bst1, sizeof(bst1));
215 	bzero(&bst2, sizeof(bst2));
216 	bzero(&ist1, sizeof(ist1));
217 	bzero(&ist2, sizeof(ist2));
218 
219 	if (ac > 0)
220 		loaddelay(&delay, av[0]);
221 
222 	for (count = 0; ; ++count) {
223 		collect_bstats(&bst1);
224 		collect_iostats(&ist1);
225 		if (count) {
226 			if ((count & 15) == 1) {
227 				printf(bstats_title"\t"iostats_title"\n");
228 			}
229 			print_bstats(&bst1, &bst2);
230 			printf("\t");
231 			print_iostats(&ist1, &ist2);
232 			printf("\n");
233 		}
234 		bcopy(&bst1, &bst2, sizeof(bst2));
235 		bcopy(&ist1, &ist2, sizeof(ist2));
236 		nanosleep(&delay, NULL);
237 	}
238 }
239 
240 /*
241  * Convert a delay string (e.g. "0.1") into a timespec.
242  */
243 static
244 void
245 loaddelay(struct timespec *ts, const char *arg)
246 {
247 	double d;
248 
249 	d = strtod(arg, NULL);
250 	if (d < 0.001)
251 		d = 0.001;
252 	ts->tv_sec = (int)d;
253 	ts->tv_nsec = (int)(modf(d, &d) * 1000000000.0);
254 }
255