From 8593c92347ebfccd854885a58e1831d0f95f3915 Mon Sep 17 00:00:00 2001 From: Marcus Holland-Moritz Date: Sat, 27 Apr 2024 19:17:10 +0200 Subject: [PATCH] feat(dwarfs): enable sequential access detector in FUSE driver --- doc/dwarfs.md | 7 +++++++ src/dwarfs_main.cpp | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/doc/dwarfs.md b/doc/dwarfs.md index 37f1bc20..62bdd45f 100644 --- a/doc/dwarfs.md +++ b/doc/dwarfs.md @@ -153,6 +153,13 @@ options: be an integer value. Suffixes `ms`, `s`, `m`, `h` are supported. If no suffix is given, the value will be assumed to be in seconds. +- `-o seq_detector=`*num*: + Threshold, in blocks, for the sequential access detector. If the most + recently accessed *num* blocks are sequential, then the block following + the sequence is prefetched. This can significantly increase throughput + if data is acccessed sequentially. A value of `0` completely disables + detection and prefetching. + - `-o perfmon=`*name*[`+`*name*...]: Enable performance monitoring for the list of `+`-separated components. This option is only available if the project was built with performance diff --git a/src/dwarfs_main.cpp b/src/dwarfs_main.cpp index b87c4421..9c728767 100644 --- a/src/dwarfs_main.cpp +++ b/src/dwarfs_main.cpp @@ -141,6 +141,7 @@ namespace dwarfs { namespace { constexpr size_t const kDefaultBlockSize{static_cast(512) << 10}; +constexpr size_t const kDefaultSeqDetectorThreshold{4}; struct options { // std::string isn't standard-layout on MSVC @@ -158,6 +159,7 @@ struct options { char const* cache_tidy_strategy_str{nullptr}; // TODO: const?? -> use string? char const* cache_tidy_interval_str{nullptr}; // TODO: const?? -> use string? char const* cache_tidy_max_age_str{nullptr}; // TODO: const?? -> use string? + char const* seq_detector_thresh_str{nullptr}; // TODO: const?? -> use string? #if DWARFS_PERFMON_ENABLED char const* perfmon_enabled_str{nullptr}; // TODO: const?? -> use string? char const* perfmon_trace_file_str{nullptr}; // TODO: const?? -> use string? @@ -176,6 +178,7 @@ struct options { cache_tidy_strategy block_cache_tidy_strategy{cache_tidy_strategy::NONE}; std::chrono::milliseconds block_cache_tidy_interval{std::chrono::minutes(5)}; std::chrono::milliseconds block_cache_tidy_max_age{std::chrono::minutes{10}}; + size_t seq_detector_threshold{kDefaultSeqDetectorThreshold}; bool is_help{false}; #ifdef DWARFS_BUILTIN_MANPAGE bool is_man{false}; @@ -230,6 +233,7 @@ constexpr struct ::fuse_opt dwarfs_opts[] = { DWARFS_OPT("tidy_strategy=%s", cache_tidy_strategy_str, 0), DWARFS_OPT("tidy_interval=%s", cache_tidy_interval_str, 0), DWARFS_OPT("tidy_max_age=%s", cache_tidy_max_age_str, 0), + DWARFS_OPT("seq_detector=%s", seq_detector_thresh_str, 0), DWARFS_OPT("enable_nlink", enable_nlink, 1), DWARFS_OPT("readonly", readonly, 1), DWARFS_OPT("cache_image", cache_image, 1), @@ -1074,6 +1078,7 @@ void usage(std::ostream& os, std::filesystem::path const& progname) { << " -o tidy_strategy=NAME (none)|time|swap\n" << " -o tidy_interval=TIME interval for cache tidying (5m)\n" << " -o tidy_max_age=TIME tidy blocks after this time (10m)\n" + << " -o seq_detector=NUM sequential access detector threshold (4)\n" #if DWARFS_PERFMON_ENABLED << " -o perfmon=name[+...] enable performance monitor\n" << " -o perfmon_trace=FILE write performance monitor trace file\n" @@ -1299,6 +1304,8 @@ void load_filesystem(dwarfs_userdata& userdata) { fsopts.block_cache.decompress_ratio = opts.decompress_ratio; fsopts.block_cache.mm_release = !opts.cache_image; fsopts.block_cache.init_workers = false; + fsopts.block_cache.sequential_access_detector_threshold = + opts.seq_detector_threshold; fsopts.inode_reader.readahead = opts.readahead; fsopts.metadata.enable_nlink = bool(opts.enable_nlink); fsopts.metadata.readonly = bool(opts.readonly); @@ -1486,6 +1493,11 @@ int dwarfs_main(int argc, sys_char** argv, iolayer const& iol) { return 1; } + opts.seq_detector_threshold = + opts.seq_detector_thresh_str + ? folly::to(opts.seq_detector_thresh_str) + : kDefaultSeqDetectorThreshold; + #ifdef DWARFS_BUILTIN_MANPAGE if (userdata.opts.is_man) { show_manpage(manpage::get_dwarfs_manpage(), iol);