Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
stats.cc
Go to the documentation of this file.
1// Copyright 2010-2024 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#include "ortools/util/stats.h"
15
16#include <algorithm>
17#include <cmath>
18#include <string>
19#include <vector>
20
21#include "absl/log/check.h"
22#include "absl/strings/str_format.h"
25#include "ortools/base/types.h"
27#include "ortools/port/utf8.h"
28
29namespace operations_research {
30
31std::string MemoryUsage() {
33 static const int64_t kDisplayThreshold = 2;
34 static const int64_t kKiloByte = 1024;
35 static const int64_t kMegaByte = kKiloByte * kKiloByte;
36 static const int64_t kGigaByte = kMegaByte * kKiloByte;
37 if (mem > kDisplayThreshold * kGigaByte) {
38 return absl::StrFormat("%.2lf GB", mem * 1.0 / kGigaByte);
39 } else if (mem > kDisplayThreshold * kMegaByte) {
40 return absl::StrFormat("%.2lf MB", mem * 1.0 / kMegaByte);
41 } else if (mem > kDisplayThreshold * kKiloByte) {
42 return absl::StrFormat("%2lf KB", mem * 1.0 / kKiloByte);
43 } else {
44 return absl::StrFormat("%d", mem);
45 }
46}
47
48Stat::Stat(absl::string_view name, StatsGroup* group) : name_(name) {
49 group->Register(this);
50}
51
52std::string Stat::StatString() const { return name_ + ": " + ValueAsString(); }
53
55
56void StatsGroup::Register(Stat* stat) { stats_.push_back(stat); }
57
59 for (int i = 0; i < stats_.size(); ++i) {
60 stats_[i]->Reset();
61 }
62}
63
64namespace {
65
66bool CompareStatPointers(const Stat* s1, const Stat* s2) {
67 if (s1->Priority() == s2->Priority()) {
68 if (s1->Sum() == s2->Sum()) return s1->Name() < s2->Name();
69 return (s1->Sum() > s2->Sum());
70 } else {
71 return (s1->Priority() > s2->Priority());
72 }
73}
74
75} // namespace
76
77std::string StatsGroup::StatString() const {
78 // Computes the longest name of all the stats we want to display.
79 // Also create a temporary vector so we can sort the stats by names.
80 int longest_name_size = 0;
81 std::vector<Stat*> sorted_stats;
82 for (int i = 0; i < stats_.size(); ++i) {
83 if (!stats_[i]->WorthPrinting()) continue;
84 // We support UTF8 characters in the stat names.
85 const int size = operations_research::utf8::UTF8StrLen(stats_[i]->Name());
86 longest_name_size = std::max(longest_name_size, size);
87 sorted_stats.push_back(stats_[i]);
88 }
89 switch (print_order_) {
91 std::sort(sorted_stats.begin(), sorted_stats.end(), CompareStatPointers);
92 break;
93 case SORT_BY_NAME:
94 std::sort(sorted_stats.begin(), sorted_stats.end(),
95 [](const Stat* s1, const Stat* s2) -> bool {
96 return s1->Name() < s2->Name();
97 });
98 break;
99 default:
100 LOG(FATAL) << "Unknown print order: " << print_order_;
101 }
102
103 // Do not display groups without print-worthy stats.
104 if (sorted_stats.empty()) return "";
105
106 // Pretty-print all the stats.
107 std::string result(name_ + " {\n");
108 for (int i = 0; i < sorted_stats.size(); ++i) {
109 result += " ";
110 result += sorted_stats[i]->Name();
111 result.append(longest_name_size - operations_research::utf8::UTF8StrLen(
112 sorted_stats[i]->Name()),
113 ' ');
114 result += " : " + sorted_stats[i]->ValueAsString();
115 }
116 result += "}\n";
117 return result;
118}
119
121 TimeDistribution*& ref = time_distributions_[name];
122 if (ref == nullptr) {
123 ref = new TimeDistribution(name);
124 Register(ref);
125 }
126 return ref;
127}
128
130 : Stat(name),
131 sum_(0.0),
132 average_(0.0),
133 sum_squares_from_average_(0.0),
134 min_(0.0),
135 max_(0.0),
136 num_(0) {}
137
139 : Stat(name, group),
140 sum_(0.0),
141 average_(0.0),
142 sum_squares_from_average_(0.0),
143 min_(0.0),
144 max_(0.0),
145 num_(0) {}
146
148 sum_ = 0.0;
149 average_ = 0.0;
151 min_ = 0.0;
152 max_ = 0.0;
153 num_ = 0;
154}
155
157 if (num_ == 0) {
158 min_ = value;
159 max_ = value;
160 sum_ = value;
161 average_ = value;
162 num_ = 1;
163 return;
164 }
165 min_ = std::min(min_, value);
166 max_ = std::max(max_, value);
167 sum_ += value;
168 ++num_;
169 const double delta = value - average_;
170 average_ = sum_ / num_;
172}
173
174double DistributionStat::Average() const { return average_; }
175
177 if (num_ == 0) return 0.0;
178 return sqrt(sum_squares_from_average_ / num_);
179}
180
182 const double seconds_per_cycles = CycleTimerBase::CyclesToSeconds(1);
183 return cycles * seconds_per_cycles;
184}
185
186std::string TimeDistribution::PrintCyclesAsTime(double cycles) {
187 DCHECK_GE(cycles, 0.0);
188 // This epsilon is just to avoid displaying 1000.00ms instead of 1.00s.
189 double eps1 = 1 + 1e-3;
190 double sec = CyclesToSeconds(cycles);
191 if (sec * eps1 >= 3600.0) return absl::StrFormat("%.2fh", sec / 3600.0);
192 if (sec * eps1 >= 60.0) return absl::StrFormat("%.2fm", sec / 60.0);
193 if (sec * eps1 >= 1.0) return absl::StrFormat("%.2fs", sec);
194 if (sec * eps1 >= 1e-3) return absl::StrFormat("%.2fms", sec * 1e3);
195 if (sec * eps1 >= 1e-6) return absl::StrFormat("%.2fus", sec * 1e6);
196 return absl::StrFormat("%.2fns", sec * 1e9);
197}
198
199void TimeDistribution::AddTimeInSec(double seconds) {
200 DCHECK_GE(seconds, 0.0);
201 const double cycles_per_seconds = 1.0 / CycleTimerBase::CyclesToSeconds(1);
202 AddToDistribution(seconds * cycles_per_seconds);
203}
204
206 DCHECK_GE(cycles, 0.0);
207 AddToDistribution(cycles);
208}
209
211 return absl::StrFormat(
212 "%8u [%8s, %8s] %8s %8s %8s\n", num_, PrintCyclesAsTime(min_),
213 PrintCyclesAsTime(max_), PrintCyclesAsTime(Average()),
214 PrintCyclesAsTime(StdDeviation()), PrintCyclesAsTime(sum_));
215}
216
218 DCHECK_GE(value, 0.0);
220}
221
223 return absl::StrFormat("%8u [%7.2f%%, %7.2f%%] %7.2f%% %7.2f%%\n", num_,
224 100.0 * min_, 100.0 * max_, 100.0 * Average(),
225 100.0 * StdDeviation());
226}
227
229
231 return absl::StrFormat("%8u [%8.1e, %8.1e] %8.1e %8.1e\n", num_, min_, max_,
232 Average(), StdDeviation());
233}
234
236 AddToDistribution(static_cast<double>(value));
237}
238
240 return absl::StrFormat("%8u [%8.f, %8.f] %8.2f %8.2f %8.f\n", num_, min_,
242}
243
244} // namespace operations_research
IntegerValue size
static double CyclesToSeconds(int64_t c)
Definition timer.h:89
double Average() const
Get the average of the distribution or 0.0 if empty.
Definition stats.cc:174
void AddToDistribution(double value)
Adds a value to this sequence and updates the stats.
Definition stats.cc:156
void Reset() override
Reset this statistic to the same state as if it was newly created.
Definition stats.cc:147
std::string ValueAsString() const override
Implemented by the subclasses.
Definition stats.cc:230
std::string ValueAsString() const override
Implemented by the subclasses.
Definition stats.cc:239
std::string ValueAsString() const override
Implemented by the subclasses.
Definition stats.cc:222
Base class for a statistic that can be pretty-printed.
Definition stats.h:90
std::string Name() const
Only used for display purposes.
Definition stats.h:99
virtual int Priority() const
Definition stats.h:108
virtual std::string ValueAsString() const =0
Prints information about this statistic.
Stat(absl::string_view name)
Definition stats.h:92
std::string StatString() const
Definition stats.cc:52
virtual double Sum() const
Definition stats.h:112
Base class to print a nice summary of a group of statistics.
Definition stats.h:128
TimeDistribution * LookupOrCreateTimeDistribution(std::string name)
Definition stats.cc:120
std::string StatString() const
Definition stats.cc:77
void Reset()
Calls Reset() on all the statistics registered with this group.
Definition stats.cc:58
void Register(Stat *stat)
Definition stats.cc:56
std::string ValueAsString() const override
Implemented by the subclasses.
Definition stats.cc:210
void AddTimeInSec(double seconds)
Adds a time in seconds to this distribution.
Definition stats.cc:199
static double CyclesToSeconds(double num_cycles)
Definition stats.cc:181
void AddTimeInCycles(double cycles)
Adds a time in CPU cycles to this distribution.
Definition stats.cc:205
const std::string name
A name for logging purposes.
int64_t value
void STLDeleteValues(T *v)
Definition stl_util.h:382
int UTF8StrLen(StrType str_type)
str_type should be string/StringPiece/Cord
Definition utf8.h:28
In SWIG mode, we don't want anything besides these top-level includes.
std::string MemoryUsage()
Returns the current thread's total memory usage in an human-readable string.
Definition stats.cc:31
int64_t delta
Definition resource.cc:1709