feat: added `sleep-per-seconds-during-verify` to settings.json (#6572)

* feat: added `sleep-per-seconds-during-verify` to settings.json

* Ensuring `sleep_per_seconds_during_verify > 0` in `verify_torrent` for better performance

* `#include` list reordered alphabetically

* fix: `[readability-inconsistent-declaration-parameter-name]` warning
This commit is contained in:
Mrnikifabio 2024-02-12 16:30:40 +01:00 committed by GitHub
parent cf84afda8c
commit f06cb37c06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 102 additions and 10 deletions

View File

@ -91,6 +91,7 @@ Here is a sample of the three basic types: respectively Boolean, Number and Stri
* **torrent-added-verify-mode:** String ("fast", "full", default: "fast") Whether newly-added torrents' local data should be fully verified when added, or wait and verify them on-demand later. See [#2626](https://github.com/transmission/transmission/pull/2626) for more discussion.
* **utp-enabled:** Boolean (default = true) Enable [Micro Transport Protocol (µTP)](https://en.wikipedia.org/wiki/Micro_Transport_Protocol)
* **preferred-transport:** String ("utp" = Prefer µTP, "tcp" = Prefer TCP; default = "utp") Choose your preferred transport protocol (has no effect if one of them is disabled).
* **sleep-per-seconds-during-verify:** Number (default = 100) Controls the duration in milliseconds for which the verification process will pause to reduce disk I/O pressure.
#### Peers
* **bind-address-ipv4:** String (default = "") Where to listen for peer connections. When no valid IPv4 address is provided, Transmission will bind to "0.0.0.0".

View File

@ -351,6 +351,7 @@ auto constexpr MyStatic = std::array<std::string_view, TR_N_KEYS>{
"size-bytes"sv,
"size-units"sv,
"sizeWhenDone"sv,
"sleep-per-seconds-during-verify"sv,
"sort-mode"sv,
"sort-reversed"sv,
"source"sv,

View File

@ -352,6 +352,7 @@ enum
TR_KEY_size_bytes,
TR_KEY_size_units,
TR_KEY_sizeWhenDone,
TR_KEY_sleep_per_seconds_during_verify,
TR_KEY_sort_mode,
TR_KEY_sort_reversed,
TR_KEY_source,

View File

@ -5,6 +5,7 @@
#pragma once
#include <chrono> // for tr_sleep_per_seconds_during_verify
#include <cstddef> // for size_t
#include <string>
@ -67,6 +68,7 @@ struct tr_variant;
V(TR_KEY_script_torrent_done_seeding_filename, script_torrent_done_seeding_filename, std::string, "", "") \
V(TR_KEY_seed_queue_enabled, seed_queue_enabled, bool, false, "") \
V(TR_KEY_seed_queue_size, seed_queue_size, size_t, 10U, "") \
V(TR_KEY_sleep_per_seconds_during_verify, sleep_per_seconds_during_verify, std::chrono::milliseconds, 100, "") \
V(TR_KEY_speed_limit_down, speed_limit_down, size_t, 100U, "") \
V(TR_KEY_speed_limit_down_enabled, speed_limit_down_enabled, bool, false, "") \
V(TR_KEY_speed_limit_up, speed_limit_up, size_t, 100U, "") \

View File

@ -871,6 +871,12 @@ void tr_session::setSettings(tr_session_settings&& settings_in, bool force)
dht_ = tr_dht::create(dht_mediator_, localPeerPort(), udp_core_->socket4(), udp_core_->socket6());
}
if (auto const& val = new_settings.sleep_per_seconds_during_verify;
force || val != old_settings.sleep_per_seconds_during_verify)
{
verifier_->set_sleep_per_seconds_during_verify(val);
}
// We need to update bandwidth if speed settings changed.
// It's a harmless call, so just call it instead of checking for settings changes
update_bandwidth(TR_UP);

View File

@ -10,6 +10,7 @@
#include <string>
#include <string_view>
#include <utility>
#include <chrono> //std::chrono::milliseconds
#include <fmt/core.h>
@ -424,4 +425,21 @@ tr_variant VariantConverter::save<tr_verify_added_mode>(tr_verify_added_mode con
return static_cast<int64_t>(val);
}
template<>
std::optional<std::chrono::milliseconds> VariantConverter::load<std::chrono::milliseconds>(tr_variant const& src)
{
if (auto val = src.get_if<int64_t>(); val != nullptr)
{
return std::chrono::milliseconds(*val);
}
return {};
}
template<>
tr_variant VariantConverter::save<std::chrono::milliseconds>(std::chrono::milliseconds const& val)
{
return val.count();
}
} // namespace libtransmission

View File

@ -25,15 +25,16 @@ using namespace std::chrono_literals;
namespace
{
auto constexpr SleepPerSecondDuringVerify = 100ms;
[[nodiscard]] auto current_time_secs()
{
return std::chrono::time_point_cast<std::chrono::seconds>(std::chrono::steady_clock::now());
}
} // namespace
void tr_verify_worker::verify_torrent(Mediator& verify_mediator, std::atomic<bool> const& abort_flag)
void tr_verify_worker::verify_torrent(
Mediator& verify_mediator,
std::atomic<bool> const& abort_flag,
std::chrono::milliseconds const sleep_per_seconds_during_verify)
{
verify_mediator.on_verify_started();
@ -89,12 +90,15 @@ void tr_verify_worker::verify_torrent(Mediator& verify_mediator, std::atomic<boo
auto const has_piece = sha->finish() == metainfo.piece_hash(piece);
verify_mediator.on_piece_checked(piece, has_piece);
/* sleeping even just a few msec per second goes a long
* way towards reducing IO load... */
if (auto const now = current_time_secs(); last_slept_at != now)
if (sleep_per_seconds_during_verify > std::chrono::milliseconds::zero())
{
last_slept_at = now;
std::this_thread::sleep_for(SleepPerSecondDuringVerify);
/* sleeping even just a few msec per second goes a long
* way towards reducing IO load... */
if (auto const now = current_time_secs(); last_slept_at != now)
{
last_slept_at = now;
std::this_thread::sleep_for(sleep_per_seconds_during_verify);
}
}
sha->clear();
@ -148,7 +152,7 @@ void tr_verify_worker::verify_thread_func()
current_node_ = std::move(todo_.extract(std::begin(todo_)).value());
}
verify_torrent(*current_node_->mediator_, stop_current_);
verify_torrent(*current_node_->mediator_, stop_current_, sleep_per_seconds_during_verify_);
}
}
@ -201,6 +205,11 @@ tr_verify_worker::~tr_verify_worker()
}
}
void tr_verify_worker::set_sleep_per_seconds_during_verify(std::chrono::milliseconds const sleep_per_seconds_during_verify)
{
sleep_per_seconds_during_verify_ = sleep_per_seconds_during_verify;
}
int tr_verify_worker::Node::compare(Node const& that) const noexcept
{
// prefer higher-priority torrents

View File

@ -47,6 +47,13 @@ public:
void remove(tr_sha1_digest_t const& info_hash);
void set_sleep_per_seconds_during_verify(std::chrono::milliseconds sleep_per_seconds_during_verify);
[[nodiscard]] constexpr auto sleep_per_seconds_during_verify() const noexcept
{
return sleep_per_seconds_during_verify_;
}
private:
struct Node
{
@ -72,7 +79,10 @@ private:
tr_priority_t priority_;
};
static void verify_torrent(Mediator& verify_mediator, std::atomic<bool> const& abort_flag);
static void verify_torrent(
Mediator& verify_mediator,
std::atomic<bool> const& abort_flag,
std::chrono::milliseconds sleep_per_seconds_during_verify);
void verify_thread_func();
@ -85,4 +95,6 @@ private:
std::atomic<bool> stop_current_ = false;
std::condition_variable stop_current_cv_;
std::chrono::milliseconds sleep_per_seconds_during_verify_;
};

View File

@ -454,3 +454,45 @@ TEST_F(SettingsTest, canSavePreferredTransport)
EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val));
EXPECT_EQ("tcp", val);
}
TEST_F(SettingsTest, canLoadSleepPerSecondsDuringVerify)
{
static auto constexpr Key = TR_KEY_sleep_per_seconds_during_verify;
auto constexpr ExpectedValue = 90ms;
auto settings = std::make_unique<tr_session_settings>();
auto const default_value = settings->sleep_per_seconds_during_verify;
ASSERT_NE(ExpectedValue, default_value);
auto var = tr_variant{};
tr_variantInitDict(&var, 1);
tr_variantDictAddInt(&var, Key, ExpectedValue.count());
settings->load(var);
EXPECT_EQ(ExpectedValue, settings->sleep_per_seconds_during_verify);
var.clear();
settings = std::make_unique<tr_session_settings>();
tr_variantInitDict(&var, 1);
tr_variantDictAddInt(&var, Key, 90);
settings->load(var);
EXPECT_EQ(ExpectedValue, settings->sleep_per_seconds_during_verify);
}
TEST_F(SettingsTest, canSaveSleepPerSecondsDuringVerify)
{
static auto constexpr Key = TR_KEY_sleep_per_seconds_during_verify;
static auto constexpr ExpectedValue = 90ms;
auto settings = tr_session_settings{};
auto const default_value = settings.sleep_per_seconds_during_verify;
ASSERT_NE(ExpectedValue, default_value);
auto var = tr_variant{};
tr_variantInitDict(&var, 100);
settings.sleep_per_seconds_during_verify = ExpectedValue;
var = settings.settings();
int64_t val_raw;
EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val_raw));
EXPECT_EQ(ExpectedValue, std::chrono::milliseconds{ val_raw });
}