168e079b8SMatthew Dillon /*
268e079b8SMatthew Dillon * Copyright (c) 2008 The DragonFly Project. All rights reserved.
368e079b8SMatthew Dillon *
468e079b8SMatthew Dillon * This code is derived from software contributed to The DragonFly Project
568e079b8SMatthew Dillon * by Matthew Dillon <dillon@backplane.com>
668e079b8SMatthew Dillon *
768e079b8SMatthew Dillon * Redistribution and use in source and binary forms, with or without
868e079b8SMatthew Dillon * modification, are permitted provided that the following conditions
968e079b8SMatthew Dillon * are met:
1068e079b8SMatthew Dillon *
1168e079b8SMatthew Dillon * 1. Redistributions of source code must retain the above copyright
1268e079b8SMatthew Dillon * notice, this list of conditions and the following disclaimer.
1368e079b8SMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
1468e079b8SMatthew Dillon * notice, this list of conditions and the following disclaimer in
1568e079b8SMatthew Dillon * the documentation and/or other materials provided with the
1668e079b8SMatthew Dillon * distribution.
1768e079b8SMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its
1868e079b8SMatthew Dillon * contributors may be used to endorse or promote products derived
1968e079b8SMatthew Dillon * from this software without specific, prior written permission.
2068e079b8SMatthew Dillon *
2168e079b8SMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2268e079b8SMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2368e079b8SMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2468e079b8SMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2568e079b8SMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2668e079b8SMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
2768e079b8SMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2868e079b8SMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2968e079b8SMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3068e079b8SMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
3168e079b8SMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3268e079b8SMatthew Dillon * SUCH DAMAGE.
3368e079b8SMatthew Dillon *
342ce66ea0SMatthew Dillon * $DragonFly: src/sbin/hammer/cmd_stats.c,v 1.3 2008/07/14 20:28:07 dillon Exp $
3568e079b8SMatthew Dillon */
3668e079b8SMatthew Dillon
37*41ae0862STomohiro Kusumi #include "hammer.h"
38*41ae0862STomohiro Kusumi
39d846dce0STomohiro Kusumi #include <sys/sysctl.h>
404853b773SMatthew Dillon #include <math.h>
41aedaeb59SAntonio Huete Jimenez
424853b773SMatthew Dillon static void loaddelay(struct timespec *ts, const char *arg);
434853b773SMatthew Dillon
44d846dce0STomohiro Kusumi #define _HAMMER "vfs.hammer.stats_"
4557c6cfd3STomohiro Kusumi #define bstats_title \
46d846dce0STomohiro Kusumi " lookups searches inserts deletes elements splits iterations rootiters reciters"
4757c6cfd3STomohiro Kusumi #define iostats_title \
48e0d7dd09SMatthew Dillon " f_read f_write d_read d_write i_flushes commits undo redo"
49d846dce0STomohiro Kusumi
50d846dce0STomohiro Kusumi /*
51d846dce0STomohiro Kusumi * Taken from sys/vfs/hammer/hammer_vfsops.c
52d846dce0STomohiro Kusumi */
53d846dce0STomohiro Kusumi struct btree_stats {
54d846dce0STomohiro Kusumi int64_t btree_lookups;
55d846dce0STomohiro Kusumi int64_t btree_searches;
56d846dce0STomohiro Kusumi int64_t btree_inserts;
57d846dce0STomohiro Kusumi int64_t btree_deletes;
58d846dce0STomohiro Kusumi int64_t btree_elements;
59d846dce0STomohiro Kusumi int64_t btree_splits;
60d846dce0STomohiro Kusumi int64_t btree_iterations;
61d846dce0STomohiro Kusumi int64_t btree_root_iterations;
62d846dce0STomohiro Kusumi int64_t record_iterations;
63d846dce0STomohiro Kusumi };
64d846dce0STomohiro Kusumi
65d846dce0STomohiro Kusumi struct io_stats {
66d846dce0STomohiro Kusumi int64_t file_read;
67d846dce0STomohiro Kusumi int64_t file_write;
68d846dce0STomohiro Kusumi int64_t disk_read;
69d846dce0STomohiro Kusumi int64_t disk_write;
70d846dce0STomohiro Kusumi int64_t inode_flushes;
71d846dce0STomohiro Kusumi int64_t commits;
72d846dce0STomohiro Kusumi int64_t undo;
73d846dce0STomohiro Kusumi int64_t redo;
74d846dce0STomohiro Kusumi };
75d846dce0STomohiro Kusumi
76522fafa8Szrj static __inline __always_inline
77d846dce0STomohiro Kusumi int
_sysctl(const char * name,int64_t * p)78d846dce0STomohiro Kusumi _sysctl(const char *name, int64_t *p)
79d846dce0STomohiro Kusumi {
80d846dce0STomohiro Kusumi size_t len = sizeof(*p);
81d846dce0STomohiro Kusumi return(sysctlbyname(name, p, &len, NULL, 0));
82d846dce0STomohiro Kusumi }
8357c6cfd3STomohiro Kusumi
84522fafa8Szrj static __inline __always_inline
8557c6cfd3STomohiro Kusumi void
collect_bstats(struct btree_stats * p)86d846dce0STomohiro Kusumi collect_bstats(struct btree_stats *p)
8757c6cfd3STomohiro Kusumi {
88d846dce0STomohiro Kusumi /* sysctls must exist, so ignore return values */
89d846dce0STomohiro Kusumi _sysctl(_HAMMER"btree_lookups", &p->btree_lookups);
90d846dce0STomohiro Kusumi _sysctl(_HAMMER"btree_searches", &p->btree_searches);
91d846dce0STomohiro Kusumi _sysctl(_HAMMER"btree_inserts", &p->btree_inserts);
92d846dce0STomohiro Kusumi _sysctl(_HAMMER"btree_deletes", &p->btree_deletes);
93d846dce0STomohiro Kusumi _sysctl(_HAMMER"btree_elements", &p->btree_elements);
94d846dce0STomohiro Kusumi _sysctl(_HAMMER"btree_splits", &p->btree_splits);
95d846dce0STomohiro Kusumi _sysctl(_HAMMER"btree_iterations", &p->btree_iterations);
96d846dce0STomohiro Kusumi _sysctl(_HAMMER"btree_root_iterations", &p->btree_root_iterations);
97d846dce0STomohiro Kusumi _sysctl(_HAMMER"record_iterations", &p->record_iterations);
98d846dce0STomohiro Kusumi }
99d846dce0STomohiro Kusumi
100522fafa8Szrj static __inline __always_inline
101d846dce0STomohiro Kusumi void
collect_iostats(struct io_stats * p)102d846dce0STomohiro Kusumi collect_iostats(struct io_stats *p)
103d846dce0STomohiro Kusumi {
104d846dce0STomohiro Kusumi /* sysctls must exist, so ignore return values */
105d846dce0STomohiro Kusumi _sysctl(_HAMMER"file_read", &p->file_read);
106d846dce0STomohiro Kusumi _sysctl(_HAMMER"file_write", &p->file_write);
107d846dce0STomohiro Kusumi _sysctl(_HAMMER"disk_read", &p->disk_read);
108d846dce0STomohiro Kusumi _sysctl(_HAMMER"disk_write", &p->disk_write);
109d846dce0STomohiro Kusumi _sysctl(_HAMMER"inode_flushes", &p->inode_flushes);
110d846dce0STomohiro Kusumi _sysctl(_HAMMER"commits", &p->commits);
111d846dce0STomohiro Kusumi _sysctl(_HAMMER"undo", &p->undo);
112d846dce0STomohiro Kusumi _sysctl(_HAMMER"redo", &p->redo);
113d846dce0STomohiro Kusumi }
114d846dce0STomohiro Kusumi
115522fafa8Szrj static __inline __always_inline
116d846dce0STomohiro Kusumi void
print_bstats(const struct btree_stats * p1,const struct btree_stats * p2)117d846dce0STomohiro Kusumi print_bstats(const struct btree_stats *p1, const struct btree_stats *p2)
118d846dce0STomohiro Kusumi {
119d846dce0STomohiro Kusumi printf("%10jd %10jd %10jd %10jd %10jd %10jd %10jd %10jd %10jd",
120d846dce0STomohiro Kusumi (intmax_t)(p1->btree_lookups - p2->btree_lookups),
121d846dce0STomohiro Kusumi (intmax_t)(p1->btree_searches - p2->btree_searches),
122d846dce0STomohiro Kusumi (intmax_t)(p1->btree_inserts - p2->btree_inserts),
123d846dce0STomohiro Kusumi (intmax_t)(p1->btree_deletes - p2->btree_deletes),
124d846dce0STomohiro Kusumi (intmax_t)(p1->btree_elements - p2->btree_elements),
125d846dce0STomohiro Kusumi (intmax_t)(p1->btree_splits - p2->btree_splits),
126d846dce0STomohiro Kusumi (intmax_t)(p1->btree_iterations - p2->btree_iterations),
127d846dce0STomohiro Kusumi (intmax_t)(p1->btree_root_iterations - p2->btree_root_iterations),
128d846dce0STomohiro Kusumi (intmax_t)(p1->record_iterations - p2->record_iterations));
12957c6cfd3STomohiro Kusumi /* no trailing \n */
13057c6cfd3STomohiro Kusumi }
13157c6cfd3STomohiro Kusumi
132522fafa8Szrj static __inline __always_inline
13357c6cfd3STomohiro Kusumi void
print_iostats(const struct io_stats * p1,const struct io_stats * p2)134d846dce0STomohiro Kusumi print_iostats(const struct io_stats *p1, const struct io_stats *p2)
13557c6cfd3STomohiro Kusumi {
136e0d7dd09SMatthew Dillon printf("%9jd %9jd %9jd %9jd %9jd %9jd %9jd %9jd",
137d846dce0STomohiro Kusumi (intmax_t)(p1->file_read - p2->file_read),
138d846dce0STomohiro Kusumi (intmax_t)(p1->file_write - p2->file_write),
139d846dce0STomohiro Kusumi (intmax_t)(p1->disk_read - p2->disk_read),
140d846dce0STomohiro Kusumi (intmax_t)(p1->disk_write - p2->disk_write),
14157c6cfd3STomohiro Kusumi (intmax_t)(p1->inode_flushes - p2->inode_flushes),
14257c6cfd3STomohiro Kusumi (intmax_t)(p1->commits - p2->commits),
143d846dce0STomohiro Kusumi (intmax_t)(p1->undo - p2->undo),
144d846dce0STomohiro Kusumi (intmax_t)(p1->redo - p2->redo));
14557c6cfd3STomohiro Kusumi /* no trailing \n */
14657c6cfd3STomohiro Kusumi }
14757c6cfd3STomohiro Kusumi
14868e079b8SMatthew Dillon void
hammer_cmd_bstats(char ** av,int ac)14968e079b8SMatthew Dillon hammer_cmd_bstats(char **av, int ac)
15068e079b8SMatthew Dillon {
151d846dce0STomohiro Kusumi struct btree_stats st1, st2;
1524853b773SMatthew Dillon struct timespec delay = {1, 0};
15368e079b8SMatthew Dillon int count;
15468e079b8SMatthew Dillon
155d846dce0STomohiro Kusumi bzero(&st1, sizeof(st1));
156d846dce0STomohiro Kusumi bzero(&st2, sizeof(st2));
157d846dce0STomohiro Kusumi
15868e079b8SMatthew Dillon if (ac > 0)
1594853b773SMatthew Dillon loaddelay(&delay, av[0]);
16068e079b8SMatthew Dillon
16168e079b8SMatthew Dillon for (count = 0; ; ++count) {
162d846dce0STomohiro Kusumi collect_bstats(&st1);
16368e079b8SMatthew Dillon if (count) {
16468e079b8SMatthew Dillon if ((count & 15) == 1)
16557c6cfd3STomohiro Kusumi printf(bstats_title"\n");
166d846dce0STomohiro Kusumi print_bstats(&st1, &st2);
16757c6cfd3STomohiro Kusumi printf("\n");
16868e079b8SMatthew Dillon }
169d846dce0STomohiro Kusumi bcopy(&st1, &st2, sizeof(st2));
1704853b773SMatthew Dillon nanosleep(&delay, NULL);
17168e079b8SMatthew Dillon }
17268e079b8SMatthew Dillon }
17368e079b8SMatthew Dillon
17468e079b8SMatthew Dillon void
hammer_cmd_iostats(char ** av,int ac)17568e079b8SMatthew Dillon hammer_cmd_iostats(char **av, int ac)
17668e079b8SMatthew Dillon {
177d846dce0STomohiro Kusumi struct io_stats st1, st2;
1784853b773SMatthew Dillon struct timespec delay = {1, 0};
17968e079b8SMatthew Dillon int count;
18068e079b8SMatthew Dillon
181d846dce0STomohiro Kusumi bzero(&st1, sizeof(st1));
182d846dce0STomohiro Kusumi bzero(&st2, sizeof(st2));
183d846dce0STomohiro Kusumi
18468e079b8SMatthew Dillon if (ac > 0)
1854853b773SMatthew Dillon loaddelay(&delay, av[0]);
18668e079b8SMatthew Dillon
18768e079b8SMatthew Dillon for (count = 0; ; ++count) {
188d846dce0STomohiro Kusumi collect_iostats(&st1);
18968e079b8SMatthew Dillon if (count) {
19068e079b8SMatthew Dillon if ((count & 15) == 1)
19157c6cfd3STomohiro Kusumi printf(iostats_title"\n");
192d846dce0STomohiro Kusumi print_iostats(&st1, &st2);
19357c6cfd3STomohiro Kusumi printf("\n");
19468e079b8SMatthew Dillon }
195d846dce0STomohiro Kusumi bcopy(&st1, &st2, sizeof(st2));
1964853b773SMatthew Dillon nanosleep(&delay, NULL);
19768e079b8SMatthew Dillon }
19868e079b8SMatthew Dillon }
19968e079b8SMatthew Dillon
2003f760d89STomohiro Kusumi void
hammer_cmd_stats(char ** av,int ac)2013f760d89STomohiro Kusumi hammer_cmd_stats(char **av, int ac)
2023f760d89STomohiro Kusumi {
203d846dce0STomohiro Kusumi struct btree_stats bst1, bst2;
204d846dce0STomohiro Kusumi struct io_stats ist1, ist2;
2053f760d89STomohiro Kusumi struct timespec delay = {1, 0};
2063f760d89STomohiro Kusumi int count;
2073f760d89STomohiro Kusumi
208d846dce0STomohiro Kusumi bzero(&bst1, sizeof(bst1));
209d846dce0STomohiro Kusumi bzero(&bst2, sizeof(bst2));
210d846dce0STomohiro Kusumi bzero(&ist1, sizeof(ist1));
211d846dce0STomohiro Kusumi bzero(&ist2, sizeof(ist2));
212d846dce0STomohiro Kusumi
2133f760d89STomohiro Kusumi if (ac > 0)
2143f760d89STomohiro Kusumi loaddelay(&delay, av[0]);
2153f760d89STomohiro Kusumi
2163f760d89STomohiro Kusumi for (count = 0; ; ++count) {
217d846dce0STomohiro Kusumi collect_bstats(&bst1);
218d846dce0STomohiro Kusumi collect_iostats(&ist1);
2193f760d89STomohiro Kusumi if (count) {
22052e2f1b5STomohiro Kusumi if ((count & 15) == 1)
22157c6cfd3STomohiro Kusumi printf(bstats_title"\t"iostats_title"\n");
222d846dce0STomohiro Kusumi print_bstats(&bst1, &bst2);
22357c6cfd3STomohiro Kusumi printf("\t");
224d846dce0STomohiro Kusumi print_iostats(&ist1, &ist2);
22557c6cfd3STomohiro Kusumi printf("\n");
2263f760d89STomohiro Kusumi }
227d846dce0STomohiro Kusumi bcopy(&bst1, &bst2, sizeof(bst2));
228d846dce0STomohiro Kusumi bcopy(&ist1, &ist2, sizeof(ist2));
2293f760d89STomohiro Kusumi nanosleep(&delay, NULL);
2303f760d89STomohiro Kusumi }
2313f760d89STomohiro Kusumi }
2323f760d89STomohiro Kusumi
2334853b773SMatthew Dillon /*
2344853b773SMatthew Dillon * Convert a delay string (e.g. "0.1") into a timespec.
2354853b773SMatthew Dillon */
2364853b773SMatthew Dillon static
2374853b773SMatthew Dillon void
loaddelay(struct timespec * ts,const char * arg)2384853b773SMatthew Dillon loaddelay(struct timespec *ts, const char *arg)
2394853b773SMatthew Dillon {
2404853b773SMatthew Dillon double d;
2414853b773SMatthew Dillon
2424853b773SMatthew Dillon d = strtod(arg, NULL);
2434853b773SMatthew Dillon if (d < 0.001)
2444853b773SMatthew Dillon d = 0.001;
2454853b773SMatthew Dillon ts->tv_sec = (int)d;
2464853b773SMatthew Dillon ts->tv_nsec = (int)(modf(d, &d) * 1000000000.0);
2474853b773SMatthew Dillon }
248