Skip to content

Commit a6656df

Browse files
authored
Merge pull request ceph#66001 from baum/nvmeof-client-timer
nvmeof: refactor beacon timer for exact frequency timing with drift correction
2 parents fffbb76 + ccd2024 commit a6656df

File tree

2 files changed

+71
-8
lines changed

2 files changed

+71
-8
lines changed

src/nvmeof/NVMeofGwMonitorClient.cc

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,10 @@ int NVMeofGwMonitorClient::init()
184184

185185
{
186186
std::lock_guard bl(beacon_lock);
187-
tick();
187+
// Initialize timer state for exact frequency timing
188+
next_tick_time = ceph::mono_clock::now();
189+
// Start the timer after full initialization is complete
190+
schedule_next_tick();
188191
}
189192

190193
dout(10) << "Complete." << dendl;
@@ -283,19 +286,55 @@ void NVMeofGwMonitorClient::connect_panic()
283286
void NVMeofGwMonitorClient::tick()
284287
{
285288
dout(10) << dendl;
286-
289+
auto start_time = ceph::mono_clock::now();
287290
connect_panic();
288291
disconnect_panic();
289292
send_beacon();
290293
first_beacon = false;
291-
timer.add_event_after(
292-
g_conf().get_val<std::chrono::seconds>("nvmeof_mon_client_tick_period").count(),
293-
new LambdaContext([this](int r){
294-
tick();
295-
}
296-
));
294+
295+
// Log tick execution duration
296+
log_tick_execution_duration(start_time);
297+
298+
// Schedule next tick with exact frequency timing
299+
schedule_next_tick();
297300
}
298301

302+
void NVMeofGwMonitorClient::schedule_next_tick()
303+
{
304+
ceph_assert(ceph_mutex_is_locked_by_me(beacon_lock));
305+
306+
// Calculate next tick time based on configured interval
307+
auto tick_period = g_conf().get_val<std::chrono::seconds>("nvmeof_mon_client_tick_period");
308+
next_tick_time += tick_period;
309+
310+
// Get current time to check for drift
311+
auto now = ceph::mono_clock::now();
312+
313+
// If we're behind schedule, adjust next_tick_time to prevent drift accumulation
314+
if (next_tick_time < now) {
315+
dout(1) << "Timer drift detected, adjusting next_tick_time from "
316+
<< next_tick_time << " to " << now << dendl;
317+
next_tick_time = now;
318+
}
319+
320+
// Schedule the next tick
321+
auto callback = new LambdaContext([this](int r) {
322+
tick();
323+
});
324+
325+
auto tick_time = next_tick_time;
326+
if (!timer.add_event_at(tick_time, callback)) {
327+
throw std::runtime_error("Failed to schedule timer event (timer shutting down)");
328+
}
329+
330+
// Log scheduling information for frequency analysis
331+
auto delay_ns = (next_tick_time - now).count();
332+
dout(10) << "Scheduled next tick at " << next_tick_time
333+
<< " (delay: " << delay_ns << " ns, "
334+
<< (delay_ns / 1000000.0) << " ms)" << dendl;
335+
}
336+
337+
299338
void NVMeofGwMonitorClient::shutdown()
300339
{
301340
std::lock_guard l(lock);
@@ -475,3 +514,19 @@ int NVMeofGwMonitorClient::main(std::vector<const char *> args)
475514

476515
return 0;
477516
}
517+
518+
void NVMeofGwMonitorClient::log_tick_execution_duration(const ceph::mono_clock::time_point& start_time)
519+
{
520+
auto execution_time = ceph::mono_clock::now() - start_time;
521+
auto tick_period = g_conf().get_val<std::chrono::seconds>("nvmeof_mon_client_tick_period");
522+
auto max_allowed_time = tick_period * 0.1; // 10% of tick period
523+
524+
dout(10) << "Tick execution took " << execution_time.count() / 1000000.0
525+
<< "ms" << dendl;
526+
527+
if (execution_time > max_allowed_time) {
528+
dout(1) << "WARNING: Tick execution took " << execution_time.count() / 1000000.0
529+
<< "ms, exceeding 10% of tick period (" << max_allowed_time.count() / 1000000.0
530+
<< "ms)" << dendl;
531+
}
532+
}

src/nvmeof/NVMeofGwMonitorClient.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "common/Finisher.h"
2222
#include "common/Timer.h"
2323
#include "common/LogClient.h"
24+
#include "common/ceph_time.h"
2425

2526
#include "mon/MonClient.h"
2627
#include "osdc/Objecter.h"
@@ -71,11 +72,18 @@ class NVMeofGwMonitorClient: public Dispatcher,
7172
ceph::mutex beacon_lock = ceph::make_mutex("NVMeofGw::beacon_lock");
7273
SafeTimer timer;
7374

75+
// Timer state for exact frequency timing
76+
ceph::mono_clock::time_point next_tick_time;
77+
7478
int orig_argc;
7579
const char **orig_argv;
7680

7781
void send_config_beacon();
7882
void send_beacon();
83+
84+
// Timer management for exact frequency
85+
void schedule_next_tick();
86+
void log_tick_execution_duration(const ceph::mono_clock::time_point& start_time);
7987

8088
public:
8189
NVMeofGwMonitorClient(int argc, const char **argv);

0 commit comments

Comments
 (0)