Skip to content

Commit 4b2685b

Browse files
committed
Merge branch 'bs_stats' into 'master'
Track request block sizes in stats filter. See merge request nbdkit/nbdkit!5
2 parents 1f5dc06 + 99a9aa9 commit 4b2685b

File tree

5 files changed

+156
-37
lines changed

5 files changed

+156
-37
lines changed

common/utils/cleanup.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
#ifndef NBDKIT_CLEANUP_H
3434
#define NBDKIT_CLEANUP_H
3535

36+
#ifdef __cplusplus
37+
extern "C" {
38+
#endif
39+
3640
#include <pthread.h>
3741
#include <assert.h>
3842

@@ -90,4 +94,8 @@ struct nbdkit_exports;
9094
extern void cleanup_exports_free (struct nbdkit_exports **ptr);
9195
#define CLEANUP_EXPORTS_FREE __attribute__((cleanup (cleanup_exports_free)))
9296

97+
#ifdef __cplusplus
98+
} /* extern "C" */
99+
#endif
100+
93101
#endif /* NBDKIT_CLEANUP_H */

filters/stats/Makefile.am

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ include $(top_srcdir)/common-rules.mk
3333

3434
EXTRA_DIST = nbdkit-stats-filter.pod
3535

36+
if HAVE_CXX
37+
3638
filter_LTLIBRARIES = nbdkit-stats-filter.la
3739

3840
nbdkit_stats_filter_la_SOURCES = \
39-
stats.c \
41+
stats.cpp \
4042
$(top_srcdir)/include/nbdkit-filter.h \
4143
$(NULL)
4244

@@ -68,3 +70,4 @@ nbdkit-stats-filter.1: nbdkit-stats-filter.pod \
6870
$<
6971

7072
endif HAVE_POD
73+
endif HAVE_CXX

filters/stats/nbdkit-stats-filter.pod

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,55 @@ C<nbdkit-stats-filter> is a filter that displays statistics about NBD
1212
operations, such as the number of bytes read and written. Statistics
1313
are written to a file once when nbdkit exits.
1414

15-
=head1 EXAMPLE
16-
17-
In this example we run L<guestfish(1)> over nbdkit to create an ext4
18-
filesystem on a RAM disk, and use the stats filter to display the
19-
number of read, write and trim operations involved:
20-
21-
$ nbdkit -U - --filter=stats memory 1G statsfile=/dev/stderr \
22-
--run '
23-
guestfish add-drive "" protocol:nbd server:unix:$unixsocket \
24-
discard:enable format:raw : \
25-
run : \
26-
mkfs ext4 /dev/sda
27-
'
28-
total: 370 ops, 1.282993 s, 1.04 GiB, 827.29 MiB/s
29-
read: 250 ops, 0.000364 s, 4.76 MiB, 12.78 GiB/s op, 3.71 MiB/s total
30-
write: 78 ops, 0.175715 s, 32.64 MiB, 185.78 MiB/s op, 25.44 MiB/s total
31-
trim: 33 ops, 0.000252 s, 1.00 GiB, 3968.25 GiB/s op, 798.13 MiB/s total
32-
flush: 9 ops, 0.000002 s, 0 bytes, 0 bytes/s op, 0 bytes/s total
15+
=head1 EXAMPLE OUTPUT
16+
17+
# nbdkit --filter=exitfirst --filter=stats memory 25G statsfile=example.txt
18+
# nbd-client localhost /dev/nbd1 && mkfs.ext4 /dev/nbd1 && nbd-client -d /dev/nbd1
19+
[....]
20+
# cat example.txt
21+
total: 1207 ops, 24.756059 s, 25.13 GiB, 1.02 GiB/s
22+
read: 101 ops, 0.000322 s, 1.64 MiB, 4.99 GiB/s op, 68.02 KiB/s total
23+
write: 1088 ops, 0.067040 s, 132.38 MiB, 1.93 GiB/s op, 5.35 MiB/s total
24+
trim: 14 ops, 0.002605 s, 25.00 GiB, 9596.93 GiB/s op, 1.01 GiB/s total
25+
flush: 4 ops, 0.000001 s, 0 bytes, 0 bytes/s op, 0 bytes/s total
26+
27+
READ Request sizes (top 28):
28+
blocksize request count
29+
4096 67 (66.34%)
30+
16384 7 (6.93%)
31+
8192 3 (2.97%)
32+
24576 3 (2.97%)
33+
61440 3 (2.97%)
34+
20480 2 (1.98%)
35+
28672 2 (1.98%)
36+
36864 2 (1.98%)
37+
40960 2 (1.98%)
38+
57344 2 (1.98%)
39+
65536 2 (1.98%)
40+
69632 2 (1.98%)
41+
32768 1 (0.99%)
42+
122880 1 (0.99%)
43+
126976 1 (0.99%)
44+
131072 1 (0.99%)
45+
46+
WRITE Request sizes (top 28):
47+
blocksize request count
48+
131072 1056 (97.06%)
49+
4096 18 (1.65%)
50+
20480 10 (0.92%)
51+
24576 2 (0.18%)
52+
8192 1 (0.09%)
53+
65536 1 (0.09%)
54+
55+
TRIM Request sizes (top 28):
56+
blocksize request count
57+
2147483648 12 (85.71%)
58+
16777216 1 (7.14%)
59+
1056964608 1 (7.14%)
60+
61+
ZERO Request sizes (top 28):
62+
blocksize request count
63+
3364

3465
=head1 PARAMETERS
3566

filters/stats/stats.c renamed to filters/stats/stats.cpp

Lines changed: 95 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232

3333
#include <config.h>
3434

35+
#include <map>
36+
#include <vector>
37+
#include <algorithm>
38+
3539
#include <stdio.h>
3640
#include <stdlib.h>
3741
#include <stdint.h>
@@ -47,6 +51,7 @@
4751
#include <nbdkit-filter.h>
4852

4953
#include "cleanup.h"
54+
5055
#include "tvdiff.h"
5156
#include "windows-compat.h"
5257

@@ -62,6 +67,8 @@ typedef struct {
6267
uint64_t usecs;
6368
} nbdstat;
6469

70+
typedef std::map<size_t, size_t> blksize_hist_t;
71+
6572
/* This lock protects all the stats. */
6673
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
6774
static nbdstat pread_st = { "read" };
@@ -71,6 +78,10 @@ static nbdstat zero_st = { "zero" };
7178
static nbdstat extents_st = { "extents" };
7279
static nbdstat cache_st = { "cache" };
7380
static nbdstat flush_st = { "flush" };
81+
static blksize_hist_t blksize_pread_st;
82+
static blksize_hist_t blksize_pwrite_st;
83+
static blksize_hist_t blksize_trim_st;
84+
static blksize_hist_t blksize_zero_st;
7485

7586
#define KiB 1024
7687
#define MiB 1048576
@@ -143,6 +154,50 @@ print_totals (uint64_t usecs)
143154
free (rate);
144155
}
145156

157+
static void
158+
print_histogram (const blksize_hist_t hist, int count)
159+
{
160+
double total = 0;
161+
for (auto el : hist) {
162+
total += static_cast<double> (el.second);
163+
}
164+
165+
// Sort
166+
auto pairs = std::vector<std::pair<size_t, size_t>> (hist.begin(), hist.end());
167+
std::sort(pairs.begin(), pairs.end(),
168+
[](decltype(pairs[0]) a, decltype(pairs[0]) b) {
169+
return a.second > b.second;
170+
});
171+
172+
int i = 0;
173+
for (auto el : pairs) {
174+
if (++i >= count)
175+
break;
176+
fprintf (fp, "%13zu %9zu (%.2f%%)\n",
177+
el.first, el.second, static_cast<double>(el.second) / total * 100);
178+
}
179+
}
180+
181+
static void
182+
print_blocksize_stats (void)
183+
{
184+
fprintf (fp, "\nREAD Request sizes (top 28):\n");
185+
fprintf (fp, " blocksize request count\n");
186+
print_histogram (blksize_pread_st, 28);
187+
188+
fprintf (fp, "\nWRITE Request sizes (top 28):\n");
189+
fprintf (fp, " blocksize request count\n");
190+
print_histogram (blksize_pwrite_st, 28);
191+
192+
fprintf (fp, "\nTRIM Request sizes (top 28):\n");
193+
fprintf (fp, " blocksize request count\n");
194+
print_histogram (blksize_trim_st, 28);
195+
196+
fprintf (fp, "\nZERO Request sizes (top 28):\n");
197+
fprintf (fp, " blocksize request count\n");
198+
print_histogram (blksize_zero_st, 28);
199+
}
200+
146201
static inline void
147202
print_stats (int64_t usecs)
148203
{
@@ -154,6 +209,7 @@ print_stats (int64_t usecs)
154209
print_stat (&extents_st, usecs);
155210
print_stat (&cache_st, usecs);
156211
print_stat (&flush_st, usecs);
212+
print_blocksize_stats();
157213
fflush (fp);
158214
}
159215

@@ -268,6 +324,11 @@ stats_pread (nbdkit_next *next,
268324
struct timeval start;
269325
int r;
270326

327+
{
328+
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&lock);
329+
blksize_pread_st[count]++;
330+
}
331+
271332
gettimeofday (&start, NULL);
272333
r = next->pread (next, buf, count, offset, flags, err);
273334
if (r == 0) record_stat (&pread_st, count, &start);
@@ -284,6 +345,11 @@ stats_pwrite (nbdkit_next *next,
284345
struct timeval start;
285346
int r;
286347

348+
{
349+
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&lock);
350+
blksize_pwrite_st[count]++;
351+
}
352+
287353
gettimeofday (&start, NULL);
288354
r = next->pwrite (next, buf, count, offset, flags, err);
289355
if (r == 0) record_stat (&pwrite_st, count, &start);
@@ -300,6 +366,11 @@ stats_trim (nbdkit_next *next,
300366
struct timeval start;
301367
int r;
302368

369+
{
370+
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&lock);
371+
blksize_trim_st[count]++;
372+
}
373+
303374
gettimeofday (&start, NULL);
304375
r = next->trim (next, count, offset, flags, err);
305376
if (r == 0) record_stat (&trim_st, count, &start);
@@ -331,6 +402,11 @@ stats_zero (nbdkit_next *next,
331402
struct timeval start;
332403
int r;
333404

405+
{
406+
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&lock);
407+
blksize_zero_st[count]++;
408+
}
409+
334410
gettimeofday (&start, NULL);
335411
r = next->zero (next, count, offset, flags, err);
336412
if (r == 0) record_stat (&zero_st, count, &start);
@@ -373,21 +449,24 @@ stats_cache (nbdkit_next *next,
373449
return r;
374450
}
375451

376-
static struct nbdkit_filter filter = {
377-
.name = "stats",
378-
.longname = "nbdkit stats filter",
379-
.unload = stats_unload,
380-
.config = stats_config,
381-
.config_complete = stats_config_complete,
382-
.config_help = stats_config_help,
383-
.get_ready = stats_get_ready,
384-
.pread = stats_pread,
385-
.pwrite = stats_pwrite,
386-
.trim = stats_trim,
387-
.flush = stats_flush,
388-
.zero = stats_zero,
389-
.extents = stats_extents,
390-
.cache = stats_cache,
391-
};
452+
static struct nbdkit_filter filter = []() -> nbdkit_filter {
453+
auto f = nbdkit_filter();
454+
f.name = "stats";
455+
f.longname = "nbdkit stats filter";
456+
f.unload = stats_unload;
457+
f.config = stats_config;
458+
f.config_complete = stats_config_complete;
459+
f.config_help = stats_config_help;
460+
f.get_ready = stats_get_ready;
461+
f.pread = stats_pread;
462+
f.pwrite = stats_pwrite;
463+
f.flush = stats_flush;
464+
f.trim = stats_trim;
465+
f.zero = stats_zero;
466+
f.extents = stats_extents;
467+
f.cache = stats_cache;
468+
469+
return f;
470+
}();
392471

393472
NBDKIT_REGISTER_FILTER(filter)

plugins/torrent/torrent.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,7 @@
5252
#include <libtorrent/torrent_info.hpp>
5353
#include <libtorrent/version.hpp>
5454

55-
extern "C" {
5655
#include "cleanup.h"
57-
};
5856

5957
static bool seen_torrent = false;
6058

0 commit comments

Comments
 (0)