optimize and simplify ReloadableConfig

Summary:
I found the logic for whether the config should be reloaded
unnecessarily complicated, so reduce it to deciding whether to reload
or not. This removes the need to acquire a write lock in autoreload's
common case.

Reviewed By: wez

Differential Revision: D17847699

fbshipit-source-id: 50fee1aac15cc8f896333c93459fea6510646600
This commit is contained in:
Chad Austin 2019-10-11 10:41:17 -07:00 committed by Facebook Github Bot
parent 0fcd4ced47
commit b0765887fc
2 changed files with 31 additions and 11 deletions

View File

@ -8,10 +8,12 @@
#include "eden/fs/config/ReloadableConfig.h"
#include "eden/fs/config/EdenConfig.h"
#include "eden/fs/utils/Bug.h"
namespace {
/** Throttle EdenConfig change checks, max of 1 per kEdenConfigMinPollSeconds */
constexpr std::chrono::seconds kEdenConfigMinPollSeconds{5};
/// Throttle change checks to a maximum of one per
/// kEdenConfigMinimumPollDuration.
constexpr std::chrono::seconds kEdenConfigMinimumPollDuration{5};
} // namespace
namespace facebook {
@ -24,20 +26,38 @@ ReloadableConfig::~ReloadableConfig() {}
std::shared_ptr<const EdenConfig> ReloadableConfig::getEdenConfig(
ConfigReloadBehavior reload) {
if (reload == ConfigReloadBehavior::NoReload) {
auto now = std::chrono::steady_clock::now();
// TODO: Update this monitoring code to use FileChangeMonitor.
bool shouldReload;
switch (reload) {
case ConfigReloadBehavior::NoReload:
shouldReload = false;
break;
case ConfigReloadBehavior::ForceReload:
shouldReload = true;
break;
case ConfigReloadBehavior::AutoReload: {
auto lastCheck = std::chrono::steady_clock::time_point{
std::chrono::steady_clock::duration{
lastCheck_.load(std::memory_order_acquire)}};
shouldReload = now - lastCheck >= kEdenConfigMinimumPollDuration;
break;
}
default:
auto bug = EDEN_BUG()
<< "Unexpected reload flag: " << static_cast<int>(reload);
bug.throwException();
}
if (!shouldReload) {
return state_.rlock()->config;
}
// TODO: Update this monitoring code to use FileChangeMonitor.
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
auto state = state_.wlock();
// Throttle the updates when using ConfigReloadBehavior::AutoReload
if (reload == ConfigReloadBehavior::AutoReload &&
(now - state->lastCheck) < kEdenConfigMinPollSeconds) {
return state->config;
}
state->lastCheck = now;
lastCheck_.store(now.time_since_epoch().count(), std::memory_order_release);
bool userConfigChanged = state->config->hasUserConfigFileChanged();
bool systemConfigChanged = state->config->hasSystemConfigFileChanged();

View File

@ -41,11 +41,11 @@ class ReloadableConfig {
struct ConfigState {
explicit ConfigState(const std::shared_ptr<const EdenConfig>& config)
: config{config} {}
std::chrono::steady_clock::time_point lastCheck;
std::shared_ptr<const EdenConfig> config;
};
folly::Synchronized<ConfigState> state_;
std::atomic<std::chrono::steady_clock::time_point::rep> lastCheck_;
};
} // namespace eden