14#ifndef OR_TOOLS_UTIL_TIME_LIMIT_H_
15#define OR_TOOLS_UTIL_TIME_LIMIT_H_
24#include "absl/container/flat_hash_map.h"
25#include "absl/memory/memory.h"
26#include "absl/synchronization/mutex.h"
27#include "absl/time/clock.h"
33#ifdef HAS_PERF_SUBSYSTEM
34#include "exegesis/exegesis/itineraries/perf_subsystem.h"
122 double limit_in_seconds,
123 double deterministic_limit = std::numeric_limits<double>::infinity(),
124 double instruction_limit = std::numeric_limits<double>::infinity());
135 return absl::make_unique<TimeLimit>(
136 std::numeric_limits<double>::infinity(),
137 std::numeric_limits<double>::infinity(),
138 std::numeric_limits<double>::infinity());
145 double deterministic_limit) {
146 return absl::make_unique<TimeLimit>(
147 std::numeric_limits<double>::infinity(), deterministic_limit,
148 std::numeric_limits<double>::infinity());
158 template <
typename Parameters>
161 return absl::make_unique<TimeLimit>(
163 std::numeric_limits<double>::infinity());
172 instruction_limit_ = instruction_limit;
213 return std::max(0.0, deterministic_limit_ - elapsed_deterministic_time_);
228 elapsed_deterministic_time_ += deterministic_duration;
241 const char* counter_name) {
244 deterministic_counters_[counter_name] += deterministic_duration;
252 return 1e-9 * (absl::GetCurrentTimeNanos() - start_ns_);
261 return elapsed_deterministic_time_;
274 std::atomic<bool>* external_boolean_as_limit) {
275 external_boolean_as_limit_ = external_boolean_as_limit;
282 return external_boolean_as_limit_;
289 template <
typename Parameters>
299 void ResetTimers(
double limit_in_seconds,
double deterministic_limit,
300 double instruction_limit);
302 std::string GetInstructionRetiredEventName()
const {
303 return "inst_retired:any_p:u";
306 mutable int64_t start_ns_;
310 const int64_t safety_buffer_ns_;
311 RunningMax<int64_t> running_max_;
315 double limit_in_seconds_;
317 double deterministic_limit_;
318 double elapsed_deterministic_time_;
320 std::atomic<bool>* external_boolean_as_limit_;
322#ifdef HAS_PERF_SUBSYSTEM
324 exegesis::PerfSubsystem perf_subsystem_;
327 double instruction_limit_;
331 absl::flat_hash_map<std::string, double> deterministic_counters_;
342 : time_limit_(
time_limit), stopped_boolean_(false) {
344 stopped_ =
time_limit->ExternalBooleanAsLimit();
345 if (stopped_ ==
nullptr) {
346 stopped_ = &stopped_boolean_;
347 time_limit->RegisterExternalBooleanAsLimit(stopped_);
352 if (stopped_ == &stopped_boolean_) {
353 time_limit_->RegisterExternalBooleanAsLimit(
nullptr);
360 absl::MutexLock lock(&mutex_);
361 return time_limit_->LimitReached();
365 absl::MutexLock lock(&mutex_);
370 absl::MutexLock lock(&mutex_);
375 absl::MutexLock lock(&mutex_);
376 time_limit_->AdvanceDeterministicTime(deterministic_duration);
380 absl::ReaderMutexLock lock(&mutex_);
381 return time_limit_->GetTimeLeft();
385 absl::ReaderMutexLock lock(&mutex_);
386 return time_limit_->GetElapsedDeterministicTime();
390 mutable absl::Mutex mutex_;
391 TimeLimit* time_limit_ ABSL_GUARDED_BY(mutex_);
392 std::atomic<bool> stopped_boolean_ ABSL_GUARDED_BY(mutex_);
393 std::atomic<bool>* stopped_ ABSL_GUARDED_BY(mutex_);
433 double deterministic_limit);
447 template <
typename Parameters>
450 return absl::make_unique<NestedTimeLimit>(
473 double instruction_limit)
474 : safety_buffer_ns_(static_cast<int64_t>(kSafetyBufferSeconds * 1e9)),
475 running_max_(kHistorySize),
476 external_boolean_as_limit_(nullptr) {
477 ResetTimers(limit_in_seconds, deterministic_limit, instruction_limit);
480inline void TimeLimit::ResetTimers(
double limit_in_seconds,
481 double deterministic_limit,
482 double instruction_limit) {
483 elapsed_deterministic_time_ = 0.0;
484 deterministic_limit_ = deterministic_limit;
485 instruction_limit_ = instruction_limit;
487 if (absl::GetFlag(FLAGS_time_limit_use_usertime)) {
489 limit_in_seconds_ = limit_in_seconds;
491#ifdef HAS_PERF_SUBSYSTEM
492 if (absl::GetFlag(FLAGS_time_limit_use_instruction_count)) {
493 perf_subsystem_.CleanUp();
494 perf_subsystem_.AddEvent(GetInstructionRetiredEventName());
495 perf_subsystem_.StartCollecting();
498 start_ns_ = absl::GetCurrentTimeNanos();
499 last_ns_ = start_ns_;
500 limit_ns_ = limit_in_seconds >= 1e-9 * (
kint64max - start_ns_)
502 :
static_cast<int64_t
>(limit_in_seconds * 1e9) + start_ns_;
505template <
typename Parameters>
509 std::numeric_limits<double>::infinity());
513 if (other ==
nullptr)
return;
517 std::numeric_limits<double>::infinity());
524#ifdef HAS_PERF_SUBSYSTEM
525 if (absl::GetFlag(FLAGS_time_limit_use_instruction_count)) {
526 return perf_subsystem_.ReadCounters().GetScaledOrDie(
527 GetInstructionRetiredEventName());
534 if (external_boolean_as_limit_ !=
nullptr &&
535 external_boolean_as_limit_->load()) {
543#ifdef HAS_PERF_SUBSYSTEM
549 const int64_t current_ns = absl::GetCurrentTimeNanos();
550 running_max_.Add(
std::max(safety_buffer_ns_, current_ns - last_ns_));
551 last_ns_ = current_ns;
552 if (current_ns + running_max_.GetCurrentMax() >= limit_ns_) {
553 if (absl::GetFlag(FLAGS_time_limit_use_usertime)) {
557 const double time_left_s = limit_in_seconds_ - user_timer_.
Get();
559 limit_ns_ =
static_cast<int64_t
>(time_left_s * 1e9) + last_ns_;
572 if (limit_ns_ ==
kint64max)
return std::numeric_limits<double>::infinity();
573 const int64_t delta_ns = limit_ns_ - absl::GetCurrentTimeNanos();
574 if (delta_ns < 0)
return 0.0;
575 if (absl::GetFlag(FLAGS_time_limit_use_usertime)) {
576 return std::max(limit_in_seconds_ - user_timer_.
Get(), 0.0);
578 return delta_ns * 1e-9;
#define DCHECK_LE(val1, val2)
Provides a way to nest time limits for algorithms where a certain part of the computation is bounded ...
static std::unique_ptr< NestedTimeLimit > FromBaseTimeLimitAndParameters(TimeLimit *time_limit, const Parameters ¶meters)
Creates a time limit object initialized from a base time limit and an object that provides methods ma...
TimeLimit * GetTimeLimit()
Returns a time limit object that represents the combination of the overall time limit and the part-sp...
~NestedTimeLimit()
Updates elapsed deterministic time in the base time limit object.
NestedTimeLimit(TimeLimit *base_time_limit, double limit_in_seconds, double deterministic_limit)
Creates the nested time limit.
void UpdateLocalLimit(TimeLimit *local_limit)
double GetTimeLeft() const
SharedTimeLimit(TimeLimit *time_limit)
double GetElapsedDeterministicTime() const
bool LimitReached() const
void AdvanceDeterministicTime(double deterministic_duration)
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
double GetInstructionsLeft()
Returns the number of instructions left to reach the limit.
static std::unique_ptr< TimeLimit > FromParameters(const Parameters ¶meters)
Creates a time limit object initialized from an object that provides methods max_time_in_seconds() an...
static const double kSafetyBufferSeconds
void ResetLimitFromParameters(const Parameters ¶meters)
Sets new time limits.
double GetDeterministicTimeLeft() const
Returns the remaining deterministic time before LimitReached() returns true due to the deterministic ...
double GetTimeLeft() const
Returns the time left on this limit, or 0 if the limit was reached (it never returns a negative value...
void SetInstructionLimit(double instruction_limit)
Sets the instruction limit.
std::atomic< bool > * ExternalBooleanAsLimit() const
Returns the current external Boolean limit.
friend class ParallelTimeLimit
double ReadInstructionCounter()
Returns the number of instructions executed since the creation of this object.
void RegisterExternalBooleanAsLimit(std::atomic< bool > *external_boolean_as_limit)
Registers the external Boolean to check when LimitReached() is called.
std::string DebugString() const
Returns information about the time limit object in a human-readable form.
bool LimitReached()
Returns true when the external limit is true, or the deterministic time is over the deterministic lim...
static std::unique_ptr< TimeLimit > Infinite()
Creates a time limit object that uses infinite time for wall time, deterministic time and instruction...
static std::unique_ptr< TimeLimit > FromDeterministicTime(double deterministic_limit)
Creates a time limit object that puts limit only on the deterministic time.
TimeLimit(const TimeLimit &)=delete
static const int kHistorySize
double GetElapsedDeterministicTime() const
Returns the elapsed deterministic time since the construction of this object.
void AdvanceDeterministicTime(double deterministic_duration, const char *counter_name)
Advances the deterministic time.
void MergeWithGlobalTimeLimit(TimeLimit *other)
TimeLimit & operator=(const TimeLimit &)=delete
double GetElapsedTime() const
Returns the time elapsed in seconds since the construction of this object.
void AdvanceDeterministicTime(double deterministic_duration)
Advances the deterministic time.
ModelSharedTimeLimit * time_limit
static const int64_t kint64max
Collection of objects used to extend the Constraint Solver library.
ABSL_DECLARE_FLAG(bool, time_limit_use_usertime)
Enables changing the behavior of the TimeLimit class to use -b usertime instead of walltime.