CernVM-FS  2.13.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
algorithm.cc
Go to the documentation of this file.
1 
7 #ifndef __STDC_FORMAT_MACROS
8 // NOLINTNEXTLINE
9 #define __STDC_FORMAT_MACROS
10 #endif
11 
12 #include "util/algorithm.h"
13 
14 #include <algorithm>
15 #include <cassert>
16 #include <cmath>
17 #include <cstdio>
18 #include <cstdlib>
19 #include <cstring>
20 
21 #include "util/string.h"
22 
23 
24 #ifdef CVMFS_NAMESPACE_GUARD
25 namespace CVMFS_NAMESPACE_GUARD {
26 #endif
27 
29 
30 
31 double DiffTimeSeconds(struct timeval start, struct timeval end) {
32  // Time subtraction, from GCC documentation
33  if (end.tv_usec < start.tv_usec) {
34  const int64_t nsec = (end.tv_usec - start.tv_usec) / 1000000 + 1;
35  start.tv_usec -= 1000000 * nsec;
36  start.tv_sec += nsec;
37  }
38  if (end.tv_usec - start.tv_usec > 1000000) {
39  const int64_t nsec = (end.tv_usec - start.tv_usec) / 1000000;
40  start.tv_usec += 1000000 * nsec;
41  start.tv_sec -= nsec;
42  }
43 
44  // Compute the time remaining to wait in microseconds.
45  // tv_usec is certainly positive.
46  const uint64_t elapsed_usec =
47  ((end.tv_sec - start.tv_sec) * 1000000) + (end.tv_usec - start.tv_usec);
48  return static_cast<double>(elapsed_usec) / 1000000.0;
49 }
50 
51 
53  assert(!running_);
54 
55  gettimeofday(&start_, NULL);
56  running_ = true;
57 }
58 
59 
61  assert(running_);
62 
63  gettimeofday(&end_, NULL);
64  running_ = false;
65 }
66 
67 
69  start_ = timeval();
70  end_ = timeval();
71  running_ = false;
72 }
73 
74 
75 double StopWatch::GetTime() const {
76  assert(!running_);
77 
78  return DiffTimeSeconds(start_, end_);
79 }
80 
81 namespace {
82 
83 static unsigned int CountDigits(uint64_t n) {
84  if (n == 0) {
85  return 1;
86  }
87  return static_cast<unsigned int>(floor(log10(static_cast<double>(n)))) + 1;
88 }
89 
90 static std::string GenerateStars(unsigned int n) { return std::string(n, '*'); }
91 
92 } // anonymous namespace
93 
94 Log2Histogram::Log2Histogram(unsigned int nbins) {
95  assert(nbins != 0);
96  this->bins_.assign(nbins + 1, 0); // +1 for overflow bin.
97  this->boundary_values_.assign(nbins + 1, 0); // +1 to avoid big if statement
98 
99  unsigned int i;
100  for (i = 1; i <= nbins; i++) {
101  this->boundary_values_[i] = (1 << ((i - 1) + 1));
102  }
103 }
104 
105 std::vector<atomic_int32> UTLog2Histogram::GetBins(const Log2Histogram &h) {
106  return h.bins_;
107 }
108 
109 unsigned int Log2Histogram::GetQuantile(float n) {
110  const uint64_t total = this->N();
111  // pivot is the index of the element corresponding to the requested quantile
112  uint64_t pivot = static_cast<uint64_t>(static_cast<float>(total) * n);
113  float normalized_pivot = 0.0;
114  // now we iterate through all the bins
115  // note that we _exclude_ the overflow bin
116  unsigned int i = 0;
117  for (i = 1; i <= this->bins_.size() - 1; i++) {
118  const unsigned int bin_value =
119  static_cast<unsigned int>(atomic_read32(&(this->bins_[i])));
120  if (pivot <= bin_value) {
121  normalized_pivot = static_cast<float>(pivot)
122  / static_cast<float>(bin_value);
123  break;
124  }
125  pivot -= bin_value;
126  }
127  if (i >= this->bins_.size()) {
128  return this->boundary_values_[this->bins_.size() - 1];
129  }
130  // now i stores the index of the bin corresponding to the requested quantile
131  // and normalized_pivot is the element we want inside the bin
132  const unsigned int min_value = this->boundary_values_[i - 1];
133  const unsigned int max_value = this->boundary_values_[i];
134  // and we return the linear interpolation
135  return min_value
136  + static_cast<unsigned int>(static_cast<float>(max_value - min_value)
137  * normalized_pivot);
138 }
139 
140 std::string Log2Histogram::ToString() {
141  unsigned int i = 0;
142 
143  unsigned int max_left_boundary_count = 1;
144  unsigned int max_right_boundary_count = 1;
145  unsigned int max_value_count = 1;
146  unsigned int max_stars = 0;
147  unsigned int max_bins = 0;
148  const unsigned int total_stars = 38;
149  uint64_t total_sum_of_bins = 0;
150 
151  for (i = 1; i <= this->bins_.size() - 1; i++) {
152  max_left_boundary_count = std::max(max_left_boundary_count,
153  CountDigits(boundary_values_[i] / 2));
154  max_right_boundary_count = std::max(max_right_boundary_count,
155  CountDigits(boundary_values_[i] - 1));
156  max_value_count = std::max(max_value_count,
157  CountDigits(atomic_read32(&(this->bins_[i]))));
158  max_bins = std::max(
159  max_bins, static_cast<unsigned int>(atomic_read32(&(this->bins_[i]))));
160  total_sum_of_bins += static_cast<unsigned int>(
161  atomic_read32(&(this->bins_[i])));
162  }
163 
164  max_bins = std::max(
165  max_bins, static_cast<unsigned int>(atomic_read32(&(this->bins_[0]))));
166  total_sum_of_bins += static_cast<unsigned int>(
167  atomic_read32(&(this->bins_[0])));
168 
169  if (total_sum_of_bins != 0) {
170  max_stars = max_bins * total_stars / total_sum_of_bins;
171  }
172 
173  const std::string format =
174  " %" +
175  StringifyUint(max_left_boundary_count < 2 ? 2 : max_left_boundary_count) +
176  "d -> %" + StringifyUint(max_right_boundary_count) + "d : %" +
177  StringifyUint(max_value_count) + "d | %" +
178  StringifyUint(max_stars < 12 ? 12 : max_stars) + "s |\n";
179 
180  const std::string title_format =
181  " %" +
183  (max_left_boundary_count < 2 ? 2 : max_left_boundary_count) +
184  max_right_boundary_count + 4) +
185  "s | %" + StringifyUint(max_value_count + 4) + "s | %" +
186  StringifyUint(max_stars < 12 ? 12 : max_stars) + "s |\n";
187 
188  const std::string overflow_format =
189  "%" +
190  StringifyUint(max_left_boundary_count + max_right_boundary_count + 5) +
191  "s : %" + StringifyUint(max_value_count + 4) + "d | %" +
192  StringifyUint(max_stars < 12 ? 12 : max_stars) + "s |\n";
193 
194  const std::string total_format =
195  "%" +
196  StringifyUint(max_left_boundary_count + max_right_boundary_count + 5 < 8
197  ? 8
198  : max_left_boundary_count + max_right_boundary_count +
199  5) +
200  "s : %" + StringifyUint(max_value_count + 4) + "lld\n";
201 
202  std::string result_string = "";
203 
204  const unsigned int kBufSize = 300;
205  char buffer[kBufSize];
206  memset(buffer, 0, sizeof(buffer));
207 
208  snprintf(
209  buffer, kBufSize, title_format.c_str(), "nsec", "count", "distribution");
210  result_string += buffer;
211  memset(buffer, 0, sizeof(buffer));
212 
213  for (i = 1; i <= this->bins_.size() - 1; i++) {
214  unsigned int n_of_stars = 0;
215  if (total_sum_of_bins != 0) {
216  n_of_stars = static_cast<unsigned int>(atomic_read32(&(this->bins_[i])))
217  * total_stars / total_sum_of_bins;
218  }
219 
220  snprintf(buffer,
221  kBufSize,
222  format.c_str(),
223  boundary_values_[i - 1],
224  boundary_values_[i] - 1,
225  static_cast<unsigned int>(atomic_read32(&this->bins_[i])),
226  GenerateStars(n_of_stars).c_str());
227  result_string += buffer;
228  memset(buffer, 0, sizeof(buffer));
229  }
230 
231  unsigned int n_of_stars = 0;
232  if (total_sum_of_bins != 0) {
233  n_of_stars = static_cast<unsigned int>(atomic_read32(&(this->bins_[0])))
234  * total_stars / total_sum_of_bins;
235  }
236 
237  snprintf(buffer,
238  kBufSize,
239  overflow_format.c_str(),
240  "overflow",
241  static_cast<unsigned int>(atomic_read32(&(this->bins_[0]))),
242  GenerateStars(n_of_stars).c_str());
243  result_string += buffer;
244  memset(buffer, 0, sizeof(buffer));
245 
246  snprintf(buffer, kBufSize, total_format.c_str(), "total", total_sum_of_bins);
247  result_string += buffer;
248  memset(buffer, 0, sizeof(buffer));
249 
250  const float qs[15] = {.1, .2, .25, .3, .4, .5, .6, .7,
251  .75, .8, .9, .95, .99, .995, .999};
252  snprintf(buffer, kBufSize,
253  "\n\nQuantiles\n"
254  "%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,"
255  "%0.4f,%0.4f,%0.4f,%0.4f\n"
256  "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n"
257  "End Quantiles"
258  "\n-----------------------\n",
259  qs[0], qs[1], qs[2], qs[3], qs[4], qs[5], qs[6], qs[7], qs[8], qs[9],
260  qs[10], qs[11], qs[12], qs[13], qs[14], GetQuantile(qs[0]),
261  GetQuantile(qs[1]), GetQuantile(qs[2]), GetQuantile(qs[3]),
262  GetQuantile(qs[4]), GetQuantile(qs[5]), GetQuantile(qs[6]),
263  GetQuantile(qs[7]), GetQuantile(qs[8]), GetQuantile(qs[9]),
264  GetQuantile(qs[10]), GetQuantile(qs[11]), GetQuantile(qs[12]),
265  GetQuantile(qs[13]), GetQuantile(qs[14]));
266 
267  result_string += buffer;
268  memset(buffer, 0, sizeof(buffer));
269 
270  return result_string;
271 }
272 
274  printf("%s", this->ToString().c_str());
275 }
276 
277 #ifdef CVMFS_NAMESPACE_GUARD
278 } // namespace CVMFS_NAMESPACE_GUARD
279 #endif
std::vector< atomic_int32 > bins_
Definition: algorithm.h:183
double DiffTimeSeconds(struct timeval start, struct timeval end)
Definition: algorithm.cc:31
double GetTime() const
Definition: algorithm.cc:75
void Reset()
Definition: algorithm.cc:68
static std::string GenerateStars(unsigned int n)
Definition: algorithm.cc:90
assert((mem||(size==0))&&"Out Of Memory")
Log2Histogram(unsigned int nbins)
Definition: algorithm.cc:94
std::string StringifyUint(const uint64_t value)
Definition: string.cc:83
unsigned int GetQuantile(float n)
Definition: algorithm.cc:109
std::string ToString()
Definition: algorithm.cc:140
static unsigned int CountDigits(uint64_t n)
Definition: algorithm.cc:83
void PrintLog2Histogram()
Definition: algorithm.cc:273
void Stop()
Definition: algorithm.cc:60
CVMFS_EXPORT const LogSource const int const char * format
Definition: exception.h:33
static bool g_is_enabled
Definition: algorithm.h:201
void Start()
Definition: algorithm.cc:52
std::vector< atomic_int32 > GetBins(const Log2Histogram &h)
Definition: algorithm.cc:105