sbin/hammer: Cleanup blocks with a single statement
[dragonfly.git] / sbin / hammer / cmd_stats.c
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    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 disk_read;
69         int64_t disk_write;
70         int64_t inode_flushes;
71         int64_t commits;
72         int64_t undo;
73         int64_t redo;
74 };
75
76 static __inline __always_inline
77 int
78 _sysctl(const char *name, int64_t *p)
79 {
80         size_t len = sizeof(*p);
81         return(sysctlbyname(name, p, &len, NULL, 0));
82 }
83
84 static __inline __always_inline
85 void
86 collect_bstats(struct btree_stats *p)
87 {
88         /* sysctls must exist, so ignore return values */
89         _sysctl(_HAMMER"btree_lookups", &p->btree_lookups);
90         _sysctl(_HAMMER"btree_searches", &p->btree_searches);
91         _sysctl(_HAMMER"btree_inserts", &p->btree_inserts);
92         _sysctl(_HAMMER"btree_deletes", &p->btree_deletes);
93         _sysctl(_HAMMER"btree_elements", &p->btree_elements);
94         _sysctl(_HAMMER"btree_splits", &p->btree_splits);
95         _sysctl(_HAMMER"btree_iterations", &p->btree_iterations);
96         _sysctl(_HAMMER"btree_root_iterations", &p->btree_root_iterations);
97         _sysctl(_HAMMER"record_iterations", &p->record_iterations);
98 }
99
100 static __inline __always_inline
101 void
102 collect_iostats(struct io_stats *p)
103 {
104         /* sysctls must exist, so ignore return values */
105         _sysctl(_HAMMER"file_read", &p->file_read);
106         _sysctl(_HAMMER"file_write", &p->file_write);
107         _sysctl(_HAMMER"disk_read", &p->disk_read);
108         _sysctl(_HAMMER"disk_write", &p->disk_write);
109         _sysctl(_HAMMER"inode_flushes", &p->inode_flushes);
110         _sysctl(_HAMMER"commits", &p->commits);
111         _sysctl(_HAMMER"undo", &p->undo);
112         _sysctl(_HAMMER"redo", &p->redo);
113 }
114
115 static __inline __always_inline
116 void
117 print_bstats(const struct btree_stats *p1, const struct btree_stats *p2)
118 {
119         printf("%10jd %10jd %10jd %10jd %10jd %10jd %10jd %10jd %10jd",
120                 (intmax_t)(p1->btree_lookups - p2->btree_lookups),
121                 (intmax_t)(p1->btree_searches - p2->btree_searches),
122                 (intmax_t)(p1->btree_inserts - p2->btree_inserts),
123                 (intmax_t)(p1->btree_deletes - p2->btree_deletes),
124                 (intmax_t)(p1->btree_elements - p2->btree_elements),
125                 (intmax_t)(p1->btree_splits - p2->btree_splits),
126                 (intmax_t)(p1->btree_iterations - p2->btree_iterations),
127                 (intmax_t)(p1->btree_root_iterations - p2->btree_root_iterations),
128                 (intmax_t)(p1->record_iterations - p2->record_iterations));
129                 /* no trailing \n */
130 }
131
132 static __inline __always_inline
133 void
134 print_iostats(const struct io_stats *p1, const struct io_stats *p2)
135 {
136         printf("%9jd %9jd %9jd %9jd %9jd %9jd %9jd %9jd",
137                 (intmax_t)(p1->file_read - p2->file_read),
138                 (intmax_t)(p1->file_write - p2->file_write),
139                 (intmax_t)(p1->disk_read - p2->disk_read),
140                 (intmax_t)(p1->disk_write - p2->disk_write),
141                 (intmax_t)(p1->inode_flushes - p2->inode_flushes),
142                 (intmax_t)(p1->commits - p2->commits),
143                 (intmax_t)(p1->undo - p2->undo),
144                 (intmax_t)(p1->redo - p2->redo));
145                 /* no trailing \n */
146 }
147
148 void
149 hammer_cmd_bstats(char **av, int ac)
150 {
151         struct btree_stats st1, st2;
152         struct timespec delay = {1, 0};
153         int count;
154
155         bzero(&st1, sizeof(st1));
156         bzero(&st2, sizeof(st2));
157
158         if (ac > 0)
159                 loaddelay(&delay, av[0]);
160
161         for (count = 0; ; ++count) {
162                 collect_bstats(&st1);
163                 if (count) {
164                         if ((count & 15) == 1)
165                                 printf(bstats_title"\n");
166                         print_bstats(&st1, &st2);
167                         printf("\n");
168                 }
169                 bcopy(&st1, &st2, sizeof(st2));
170                 nanosleep(&delay, NULL);
171         }
172 }
173
174 void
175 hammer_cmd_iostats(char **av, int ac)
176 {
177         struct io_stats st1, st2;
178         struct timespec delay = {1, 0};
179         int count;
180
181         bzero(&st1, sizeof(st1));
182         bzero(&st2, sizeof(st2));
183
184         if (ac > 0)
185                 loaddelay(&delay, av[0]);
186
187         for (count = 0; ; ++count) {
188                 collect_iostats(&st1);
189                 if (count) {
190                         if ((count & 15) == 1)
191                                 printf(iostats_title"\n");
192                         print_iostats(&st1, &st2);
193                         printf("\n");
194                 }
195                 bcopy(&st1, &st2, sizeof(st2));
196                 nanosleep(&delay, NULL);
197         }
198 }
199
200 void
201 hammer_cmd_stats(char **av, int ac)
202 {
203         struct btree_stats bst1, bst2;
204         struct io_stats ist1, ist2;
205         struct timespec delay = {1, 0};
206         int count;
207
208         bzero(&bst1, sizeof(bst1));
209         bzero(&bst2, sizeof(bst2));
210         bzero(&ist1, sizeof(ist1));
211         bzero(&ist2, sizeof(ist2));
212
213         if (ac > 0)
214                 loaddelay(&delay, av[0]);
215
216         for (count = 0; ; ++count) {
217                 collect_bstats(&bst1);
218                 collect_iostats(&ist1);
219                 if (count) {
220                         if ((count & 15) == 1)
221                                 printf(bstats_title"\t"iostats_title"\n");
222                         print_bstats(&bst1, &bst2);
223                         printf("\t");
224                         print_iostats(&ist1, &ist2);
225                         printf("\n");
226                 }
227                 bcopy(&bst1, &bst2, sizeof(bst2));
228                 bcopy(&ist1, &ist2, sizeof(ist2));
229                 nanosleep(&delay, NULL);
230         }
231 }
232
233 /*
234  * Convert a delay string (e.g. "0.1") into a timespec.
235  */
236 static
237 void
238 loaddelay(struct timespec *ts, const char *arg)
239 {
240         double d;
241
242         d = strtod(arg, NULL);
243         if (d < 0.001)
244                 d = 0.001;
245         ts->tv_sec = (int)d;
246         ts->tv_nsec = (int)(modf(d, &d) * 1000000000.0);
247 }