3838#include < TMessage.h>
3939#include < TClonesArray.h>
4040
41+ #include < algorithm>
4142#include < vector>
4243#include < memory>
4344
@@ -51,6 +52,13 @@ using DataHeader = o2::header::DataHeader;
5152constexpr unsigned int MONITORING_QUEUE_SIZE = 100 ;
5253constexpr unsigned int MIN_RATE_LOGGING = 60 ;
5354
55+ // This should result in a minimum of 10Hz which should guarantee we do not use
56+ // much time when idle. We do not sleep at all when we are at less then 100us,
57+ // because that's what the default rate enforces in any case.
58+ constexpr int MAX_BACKOFF = 10 ;
59+ constexpr int MIN_BACKOFF_DELAY = 100 ;
60+ constexpr int BACKOFF_DELAY_STEP = 100 ;
61+
5462namespace o2 ::framework
5563{
5664
@@ -172,6 +180,7 @@ bool DataProcessingDevice::ConditionalRun()
172180 &stats = mStats ,
173181 &lastSent = mLastSlowMetricSentTimestamp ,
174182 ¤tTime = mBeginIterationTimestamp ,
183+ ¤tBackoff = mCurrentBackoff ,
175184 &monitoring = mServiceRegistry .get <Monitoring>()]()
176185 -> void {
177186 if (currentTime - lastSent < 5000 ) {
@@ -200,6 +209,7 @@ bool DataProcessingDevice::ConditionalRun()
200209 .addTag (Key::Subsystem, Value::DPL));
201210 monitoring.send (Metric{(stats.lastTotalProcessedSize / (stats.lastLatency .maxLatency ? stats.lastLatency .maxLatency : 1 ) / 1000 ), " input_rate_mb_s" }
202211 .addTag (Key::Subsystem, Value::DPL));
212+ monitoring.send (Metric{(int )currentBackoff, " current_backoff" }.addTag (Key::Subsystem, Value::DPL));
203213
204214 lastSent = currentTime;
205215 O2_SIGNPOST_END (MonitoringStatus::ID, MonitoringStatus::SEND, 0 , 0 , O2_SIGNPOST_BLUE);
@@ -267,7 +277,7 @@ bool DataProcessingDevice::ConditionalRun()
267277 if (active == false ) {
268278 mServiceRegistry .get <CallbackService>()(CallbackService::Id::Idle);
269279 }
270- mRelayer .processDanglingInputs (mExpirationHandlers , mServiceRegistry );
280+ active |= mRelayer .processDanglingInputs (mExpirationHandlers , mServiceRegistry );
271281 this ->tryDispatchComputation ();
272282
273283 sendRelayerMetrics ();
@@ -308,6 +318,23 @@ bool DataProcessingDevice::ConditionalRun()
308318 switchState (StreamingState::Idle);
309319 return true ;
310320 }
321+ // Update the backoff factor
322+ //
323+ // In principle we should use 1/rate for MIN_BACKOFF_DELAY and (1/maxRate -
324+ // 1/minRate)/ 2^MAX_BACKOFF for BACKOFF_DELAY_STEP. We hardcode the values
325+ // for the moment to some sensible default.
326+ if (active) {
327+ mCurrentBackoff = std::max (0 , mCurrentBackoff - 1 );
328+ } else {
329+ mCurrentBackoff = std::min (MAX_BACKOFF, mCurrentBackoff + 1 );
330+ }
331+
332+ if (mCurrentBackoff != 0 ) {
333+ auto delay = (rand () % ((1 << mCurrentBackoff ) - 1 )) * BACKOFF_DELAY_STEP;
334+ if (delay > MIN_BACKOFF_DELAY) {
335+ WaitFor (std::chrono::microseconds (delay - MIN_BACKOFF_DELAY));
336+ }
337+ }
311338 return true ;
312339}
313340
0 commit comments