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