Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#Centipede Enable custom interval adjustments in PeriodicAction #1263

Merged
merged 1 commit into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion centipede/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,6 @@ cc_library(
deps = [
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/synchronization",
"@com_google_absl//absl/time",
],
Expand Down
11 changes: 5 additions & 6 deletions centipede/distill.cc
Original file line number Diff line number Diff line change
Expand Up @@ -421,12 +421,11 @@ int Distill(const Environment &env, const DistillOptions &opts) {
<< " unique: " << stats.num_byte_unique_elts
<< " distilled: " << stats.num_feature_unique_elts;
},
{
// Seeing 0's at the beginning is not interesting, unless debugging.
.delay = absl::Seconds(ABSL_VLOG_IS_ON(1) ? 0 : 60),
// Again, increase the frequency with --v >= 1 to aid debugging.
.interval = absl::Seconds(ABSL_VLOG_IS_ON(1) ? 10 : 60),
},
// Seeing 0's at the beginning is not interesting, unless debugging.
// Likewise, increase the frequency --v >= 1 to aid debugging.
PeriodicAction::ConstDelayConstInterval(
absl::Seconds(ABSL_VLOG_IS_ON(1) ? 0 : 60),
absl::Seconds(ABSL_VLOG_IS_ON(1) ? 10 : 60)),
};
// The RAM pool shared between all the `DistillToOneOutputShard()` threads.
perf::ResourcePool ram_pool{kRamQuota};
Expand Down
22 changes: 10 additions & 12 deletions centipede/periodic_action.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@

#include "./centipede/periodic_action.h"

#include <cstdint>
#include <memory>
#include <thread>
#include <utility>

#include "absl/base/thread_annotations.h"
#include "absl/functional/any_invocable.h"
#include "absl/log/check.h"
#include "absl/synchronization/mutex.h"
#include "absl/synchronization/notification.h"
#include "absl/time/time.h"
Expand All @@ -32,12 +32,7 @@ class PeriodicAction::Impl {
Impl(absl::AnyInvocable<void()> action, PeriodicAction::Options options)
: action_{std::move(action)},
options_{std::move(options)},
thread_{[this]() { RunLoop(); }} {
// NOTE: Allow `options_.delay` to be `absl::InfiniteDuration()`: that's a
// valid use case, where the run-loop actually starts looping only after a
// first explicit nudge.
CHECK_GT(options_.interval, absl::ZeroDuration());
}
thread_{[this]() { RunLoop(); }} {}

void Stop() {
StopAsync();
Expand All @@ -54,8 +49,8 @@ class PeriodicAction::Impl {
if (!stop_.HasBeenNotified()) {
// Prime the run-loop to exit next time it re-checks `stop_`.
stop_.Notify();
// Nudge the run-loop out of the sleeping phase, if it's there: the loop
// immediately goes to re-check `stop_` and exits.
// Nudge the run-loop out of the sleeping phase, if it's currently idling
// there: the loop immediately goes to re-check `stop_` and exits.
{
absl::MutexLock lock{&nudge_mu_};
nudge_ = true;
Expand All @@ -70,10 +65,13 @@ class PeriodicAction::Impl {

private:
void RunLoop() {
SleepUnlessWokenByNudge(options_.delay);
uint64_t iteration = 0;
while (!stop_.HasBeenNotified()) {
action_();
SleepUnlessWokenByNudge(options_.interval);
SleepUnlessWokenByNudge(options_.sleep_before_each(iteration));
if (!stop_.HasBeenNotified()) {
action_();
}
++iteration;
}
}

Expand Down
43 changes: 35 additions & 8 deletions centipede/periodic_action.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#ifndef FUZZTEST_CENTIPEDE_PERIODIC_ACTION_H_
#define FUZZTEST_CENTIPEDE_PERIODIC_ACTION_H_

#include <cstdint>
#include <memory>

#include "absl/functional/any_invocable.h"
Expand All @@ -43,16 +44,42 @@ namespace centipede {
class PeriodicAction {
public:
struct Options {
// A delay before the first invocation of the callback. Allowed to be
// `absl::IniniteDuration()`: in that case, the periodic invocations are
// initiated only by a first explicit `Nudge()` call.
absl::Duration delay = absl::ZeroDuration();
// The interval between the end of one invocation of the callback and the
// start of another. Note that a nudge triggers an out-of-schedule
// invocation and resets the timer (see `Nudge()`).
absl::Duration interval = absl::InfiniteDuration();
// The interval to sleep for before a given iteration. Iteration numbers are
// 0-based.
//
// Thus, the interval before `iteration == 0` is the delay before the first
// invocation of the action, the interval before `iteration == 1` is the
// interval between the first and the second invocation, etc.
//
// This is a functor and not a fixed value to enable dynamic intervals (the
// caller can use static functor state for that). Note that
// `PeriodicAction::Nudge()` calls trigger out-of-schedule invocations and
// count as iterations (therefore incrementing the internal iteration
// counter and resetting the timer).
//
// If `sleep_before_each()` ever returns an `absl::InfiniteDuration()`, then
// periodic action execution will be paused and resumed only by the next
// `Nudge()` call.
absl::AnyInvocable<absl::Duration(uint64_t iter_num)> sleep_before_each;
};

// Convenience factory methods for common options.
static Options ConstDelayConstInterval( //
absl::Duration delay, absl::Duration interval) {
return {
[delay, interval](uint64_t i) { return i == 0 ? delay : interval; },
};
}
static Options ZeroDelayZeroInterval() {
return ConstDelayConstInterval(absl::ZeroDuration(), absl::ZeroDuration());
}
static Options ZeroDelayConstInterval(absl::Duration interval) {
return ConstDelayConstInterval(absl::ZeroDuration(), interval);
}
static Options ConstDelayZeroInterval(absl::Duration delay) {
return ConstDelayConstInterval(delay, absl::ZeroDuration());
}

PeriodicAction(absl::AnyInvocable<void()> action, Options options);

// Movable, but not copyable.
Expand Down
19 changes: 11 additions & 8 deletions centipede/periodic_action_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <algorithm>
#include <cmath>
#include <cstddef>

#include "gtest/gtest.h"
#include "absl/time/clock.h"
Expand All @@ -33,7 +34,7 @@ TEST(PeriodicActionTest, OnlyPeriodicInvocations) {
int count = 0;
PeriodicAction action{
[&count]() { ++count; },
{.delay = absl::ZeroDuration(), .interval = kPeriodicInterval},
PeriodicAction::ZeroDelayConstInterval(kPeriodicInterval),
};
absl::SleepFor(kDuration);
action.Stop();
Expand All @@ -47,16 +48,18 @@ TEST(PeriodicActionTest, OnlyNudgedInvocations) {
int count = 0;
PeriodicAction action{
[&count]() { ++count; },
// Effectively disable invocations done periodically: only explicit
// `Nudge()` calls below will trigger them.
{.delay = absl::InfiniteDuration(), .interval = absl::InfiniteDuration()},
{
// Effectively disable periodic invocations: only `Nudge()` calls
// below will trigger them.
.sleep_before_each = [](size_t) { return absl::InfiniteDuration(); },
},
};
int expected_count = 0;
const absl::Time end_time = absl::Now() + kDuration;
while (absl::Now() < end_time) {
action.Nudge();
// Sleep after a nudge, not before, to guarantee that the action has time to
// finish and increment `count`.
// Sleep after a nudge, not before, to guarantee that the action has time
// to finish and increment `count`.
absl::SleepFor(kNudgeInterval);
++expected_count;
}
Expand All @@ -82,7 +85,7 @@ TEST(PeriodicActionTest, PeriodicAndNudgedInvocations) {
int count = 0;
PeriodicAction action{
[&count]() { ++count; },
{.delay = absl::ZeroDuration(), .interval = kPeriodicInterval},
PeriodicAction::ZeroDelayConstInterval(kPeriodicInterval),
};
const absl::Time end_time = absl::Now() + kDuration;
while (absl::Now() < end_time) {
Expand Down Expand Up @@ -111,7 +114,7 @@ TEST(PeriodicActionTest, ClashingPeriodicAndNudgedInvocations) {
int count = 0;
PeriodicAction action{
[&count]() { ++count; },
{.delay = absl::ZeroDuration(), .interval = kPeriodicInterval},
PeriodicAction::ZeroDelayConstInterval(kPeriodicInterval),
};
const absl::Time end_time = absl::Now() + kDuration;
while (absl::Now() < end_time) {
Expand Down
5 changes: 1 addition & 4 deletions centipede/rusage_profiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -430,10 +430,7 @@ void RUsageProfiler::StartTimelapse( //
const auto& s = TakeSnapshot(loc, title);
if (also_log) s.Log();
},
PeriodicAction::Options{
.delay = absl::ZeroDuration(),
.interval = interval,
});
PeriodicAction::ZeroDelayConstInterval(interval));
}

void RUsageProfiler::StopTimelapse() {
Expand Down
Loading