mirror of
https://github.com/libfuse/libfuse.git
synced 2026-07-07 14:47:41 +08:00
memfs_ll: add -o null_io to bypass the content store
For benchmarking the FUSE interface itself rather than memfs's std::vector content management, add a -o null_io mount option. Writes still consume the incoming buffer (folding it into a volatile sink so the reads are not elided) but discard it; reads return random data served from a scratch buffer filled once at startup. The content store is never touched on either path. Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
This commit is contained in:
@@ -26,7 +26,9 @@
|
||||
#include <atomic>
|
||||
#include <string_view>
|
||||
#include <cstdint>
|
||||
#include <random>
|
||||
#include <fuse_lowlevel.h>
|
||||
#include <fuse_opt.h>
|
||||
#ifdef HAVE_LINUX_LIMITS_H
|
||||
#include <linux/limits.h>
|
||||
#endif
|
||||
@@ -36,6 +38,40 @@
|
||||
|
||||
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
|
||||
|
||||
// Benchmark mode: bypass the content store so the FUSE interface itself is
|
||||
// measured, not memfs's std::vector management. Writes still read the incoming
|
||||
// buffer; reads still return data (served from a random scratch buffer).
|
||||
struct memfs_config {
|
||||
int null_io;
|
||||
};
|
||||
static struct memfs_config memfs_cfg;
|
||||
|
||||
#define MEMFS_OPT(t, p) { t, offsetof(struct memfs_config, p), 1 }
|
||||
static const struct fuse_opt memfs_opt_spec[] = {
|
||||
MEMFS_OPT("null_io", null_io),
|
||||
FUSE_OPT_END
|
||||
};
|
||||
|
||||
// Random bytes filled once at startup; null_io reads copy/tile from here so the
|
||||
// per-read cost stays close to a memcpy rather than a per-byte RNG.
|
||||
static constexpr size_t NULL_IO_BUF_SIZE = 1u << 20;
|
||||
static std::vector<char> null_io_buf;
|
||||
|
||||
// null_io writes fold the incoming buffer into this volatile sink so the
|
||||
// compiler cannot elide the reads that simulate the data transfer.
|
||||
static volatile unsigned char null_io_write_sink;
|
||||
|
||||
static void null_io_fill(char *dst, size_t size)
|
||||
{
|
||||
size_t copied = 0;
|
||||
while (copied < size) {
|
||||
size_t chunk = std::min(size - copied, null_io_buf.size());
|
||||
std::copy(null_io_buf.begin(), null_io_buf.begin() + chunk,
|
||||
dst + copied);
|
||||
copied += chunk;
|
||||
}
|
||||
}
|
||||
|
||||
class Inodes;
|
||||
class Inode;
|
||||
class Dentry;
|
||||
@@ -612,6 +648,16 @@ static void memfs_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
|
||||
return;
|
||||
}
|
||||
|
||||
if (memfs_cfg.null_io) {
|
||||
// touch every byte so the data transfer is real, then discard
|
||||
unsigned char acc = 0;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
acc ^= (unsigned char)buf[i];
|
||||
null_io_write_sink = acc;
|
||||
fuse_reply_write(req, size);
|
||||
return;
|
||||
}
|
||||
|
||||
inode->write_content(buf, size, offset);
|
||||
fuse_reply_write(req, size);
|
||||
}
|
||||
@@ -625,6 +671,14 @@ static void memfs_read(fuse_req_t req, fuse_ino_t ino, size_t size,
|
||||
return;
|
||||
}
|
||||
|
||||
if (memfs_cfg.null_io) {
|
||||
// serve random data without consulting the content store
|
||||
std::vector<char> content(size);
|
||||
null_io_fill(content.data(), content.size());
|
||||
fuse_reply_buf(req, content.data(), content.size());
|
||||
return;
|
||||
}
|
||||
|
||||
inode->lock();
|
||||
|
||||
if (offset >= inode->content_size()) {
|
||||
@@ -1114,6 +1168,9 @@ int main(int argc, char *argv[])
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (fuse_opt_parse(&args, &memfs_cfg, memfs_opt_spec, NULL) != 0)
|
||||
return 1;
|
||||
|
||||
if (fuse_parse_cmdline(&args, &opts) != 0)
|
||||
return 1;
|
||||
|
||||
@@ -1121,6 +1178,8 @@ int main(int argc, char *argv[])
|
||||
printf("usage: %s [options] <mountpoint>\n\n", argv[0]);
|
||||
printf("File-system specific options:\n"
|
||||
" -o opt,[opt...] mount options\n"
|
||||
" -o null_io bypass the content store for\n"
|
||||
" read/write benchmarking\n"
|
||||
" -h --help print help\n"
|
||||
"\n");
|
||||
fuse_cmdline_help();
|
||||
@@ -1141,6 +1200,13 @@ int main(int argc, char *argv[])
|
||||
goto err_out1;
|
||||
}
|
||||
|
||||
if (memfs_cfg.null_io) {
|
||||
null_io_buf.resize(NULL_IO_BUF_SIZE);
|
||||
std::mt19937 rng(0);
|
||||
for (auto &byte : null_io_buf)
|
||||
byte = static_cast<char>(rng());
|
||||
}
|
||||
|
||||
se = fuse_session_new(&args, &memfs_oper, sizeof(memfs_oper), NULL);
|
||||
if (se == NULL)
|
||||
goto err_out1;
|
||||
|
||||
Reference in New Issue
Block a user