Thrill  0.1
iostats.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * foxxll/io/iostats.cpp
3  *
4  * Part of FOXXLL. See http://foxxll.org
5  *
6  * Copyright (C) 2002-2004 Roman Dementiev <[email protected]>
7  * Copyright (C) 2008-2010 Andreas Beckmann <[email protected]>
8  * Copyright (C) 2009, 2010 Johannes Singler <[email protected]>
9  * Copyright (C) 2016 Alex Schickedanz <[email protected]>
10  *
11  * Distributed under the Boost Software License, Version 1.0.
12  * (See accompanying file LICENSE_1_0.txt or copy at
13  * http://www.boost.org/LICENSE_1_0.txt)
14  **************************************************************************/
15 
16 #include <array>
17 #include <iomanip>
18 #include <mutex>
19 #include <numeric>
20 #include <sstream>
21 #include <string>
22 
23 #include <tlx/logger/core.hpp>
24 
25 #include <foxxll/common/timer.hpp>
26 #include <foxxll/common/types.hpp>
27 #include <foxxll/io/iostats.hpp>
29 
30 namespace foxxll {
31 
32 /******************************************************************************/
33 // file_stats
34 
35 file_stats::file_stats(unsigned int device_id)
36  : device_id_(device_id),
37  read_count_(0), write_count_(0),
38  read_bytes_(0), write_bytes_(0),
39  read_time_(0.0), write_time_(0.0),
40  p_begin_read_(0.0), p_begin_write_(0.0),
41  acc_reads_(0), acc_writes_(0)
42 { }
43 
44 void file_stats::write_started(const size_t size, double now)
45 {
46  if (now == 0.0)
47  now = timestamp();
48 
49  {
50  std::unique_lock<std::mutex> write_lock(write_mutex_);
51 
52  ++write_count_;
53  write_bytes_ += size;
54  const double diff = now - p_begin_write_;
55  write_time_ += (acc_writes_++) * diff;
56  p_begin_write_ = now;
57  }
58 
60 }
61 
62 void file_stats::write_canceled(const size_t size)
63 {
64  {
65  std::unique_lock<std::mutex> write_lock(write_mutex_);
66 
67  --write_count_;
68  write_bytes_ -= size;
69  }
71 }
72 
74 {
75  double now = timestamp();
76 
77  {
78  std::unique_lock<std::mutex> write_lock(write_mutex_);
79 
80  const double diff = now - p_begin_write_;
81  write_time_ += (acc_writes_--) * diff;
82  p_begin_write_ = now;
83  }
84 
86 }
87 
88 void file_stats::write_op_finished(const size_t size, double duration)
89 {
90  std::unique_lock<std::mutex> write_lock(write_mutex_);
91 
92  ++write_count_;
93  write_time_ += duration;
94  write_bytes_ += size;
95 }
96 
97 void file_stats::read_started(const size_t size, double now)
98 {
99  if (now == 0.0)
100  now = timestamp();
101 
102  {
103  std::unique_lock<std::mutex> read_lock(read_mutex_);
104 
105  ++read_count_;
106  read_bytes_ += size;
107  const double diff = now - p_begin_read_;
108  read_time_ += (acc_reads_++) * diff;
109  p_begin_read_ = now;
110  }
111 
113 }
114 
115 void file_stats::read_canceled(const size_t size)
116 {
117  {
118  std::unique_lock<std::mutex> read_lock(read_mutex_);
119 
120  --read_count_;
121  read_bytes_ -= size;
122  }
123  read_finished();
124 }
125 
127 {
128  double now = timestamp();
129 
130  {
131  std::unique_lock<std::mutex> read_lock(read_mutex_);
132 
133  const double diff = now - p_begin_read_;
134  read_time_ += (acc_reads_--) * diff;
135  p_begin_read_ = now;
136  }
137 
139 }
140 
141 void file_stats::read_op_finished(const size_t size, double duration)
142 {
143  std::unique_lock<std::mutex> write_lock(read_mutex_);
144 
145  ++read_count_;
146  read_time_ += duration;
147  read_bytes_ += size;
148 }
149 
150 /******************************************************************************/
151 // file_stats_data
152 
154 {
156  device_id_ != a.device_id_, std::runtime_error,
157  "foxxll::file_stats_data objects do not belong to the same file/disk"
158  );
159 
160  file_stats_data fsd;
161  fsd.device_id_ = device_id_;
162 
167  fsd.read_time_ = read_time_ + a.read_time_;
169 
170  return fsd;
171 }
172 
174 {
176  device_id_ != a.device_id_, std::runtime_error,
177  "foxxll::file_stats_data objects do not belong to the same file/disk"
178  );
179 
180  file_stats_data fsd;
181  fsd.device_id_ = device_id_;
182 
187  fsd.read_time_ = read_time_ - a.read_time_;
189 
190  return fsd;
191 }
192 
193 /******************************************************************************/
194 // stats
195 
197  : creation_time_(timestamp()),
198  p_reads_(0.0), p_writes_(0.0),
199  p_begin_read_(0.0), p_begin_write_(0.0),
200  p_ios_(0.0),
201  p_begin_io_(0.0),
202 
203  acc_reads_(0.0), acc_writes_(0.0),
204  acc_ios_(0.0),
205 
206  t_waits_(0.0), p_waits_(0.0),
207  p_begin_wait_(0.0),
208  t_wait_read_(0.0), p_wait_read_(0.0),
209  p_begin_wait_read_(0.0),
210  t_wait_write_(0.0), p_wait_write_(0.0),
211  p_begin_wait_write_(0.0),
212  acc_waits_(0.0),
213  acc_wait_read_(0.0), acc_wait_write_(0.0)
214 { }
215 
216 #ifndef FOXXLL_DO_NOT_COUNT_WAIT_TIME
218 {
219  const double now = timestamp();
220  {
221  std::unique_lock<std::mutex> wait_lock(wait_mutex_);
222 
223  double diff = now - p_begin_wait_;
224  t_waits_ += acc_waits_ * diff;
225  p_begin_wait_ = now;
226  p_waits_ += (acc_waits_++) ? diff : 0.0;
227 
228  if (wait_op == WAIT_OP_READ) {
229  diff = now - p_begin_wait_read_;
230  t_wait_read_ += acc_wait_read_ * diff;
231  p_begin_wait_read_ = now;
232  p_wait_read_ += (acc_wait_read_++) ? diff : 0.0;
233  }
234  else /* if (wait_op == WAIT_OP_WRITE) */ {
235  // wait_any() is only used from write_pool and buffered_writer, so account WAIT_OP_ANY for WAIT_OP_WRITE, too
236  diff = now - p_begin_wait_write_;
237  t_wait_write_ += acc_wait_write_ * diff;
238  p_begin_wait_write_ = now;
239  p_wait_write_ += (acc_wait_write_++) ? diff : 0.0;
240  }
241  }
242 }
243 
245 {
246  const double now = timestamp();
247  {
248  std::unique_lock<std::mutex> wait_lock(wait_mutex_);
249 
250  double diff = now - p_begin_wait_;
251  t_waits_ += acc_waits_ * diff;
252  p_begin_wait_ = now;
253  p_waits_ += (acc_waits_--) ? diff : 0.0;
254 
255  if (wait_op == WAIT_OP_READ) {
256  double diff2 = now - p_begin_wait_read_;
257  t_wait_read_ += acc_wait_read_ * diff2;
258  p_begin_wait_read_ = now;
259  p_wait_read_ += (acc_wait_read_--) ? diff2 : 0.0;
260  }
261  else /* if (wait_op == WAIT_OP_WRITE) */ {
262  double diff2 = now - p_begin_wait_write_;
263  t_wait_write_ += acc_wait_write_ * diff2;
264  p_begin_wait_write_ = now;
265  p_wait_write_ += (acc_wait_write_--) ? diff2 : 0.0;
266  }
267 #ifdef FOXXLL_WAIT_LOG_ENABLED
268  if (waitlog)
269  TLX_LOG1
270  << (now - last_reset) << "\t"
271  << ((wait_op == WAIT_OP_READ) ? diff : 0.0) << "\t"
272  << ((wait_op != WAIT_OP_READ) ? diff : 0.0) << "\t"
273  << t_wait_read_ << "\t" << t_wait_write_ << "\n" << line_prefix << std::flush;
274 #endif
275  }
276 }
277 #endif
278 
279 void stats::p_write_started(const double now)
280 {
281  {
282  std::unique_lock<std::mutex> write_lock(write_mutex_);
283 
284  const double diff = now - p_begin_write_;
285  p_begin_write_ = now;
286  p_writes_ += (acc_writes_++) ? diff : 0.0;
287  }
288  {
289  std::unique_lock<std::mutex> io_lock(io_mutex_);
290 
291  const double diff = now - p_begin_io_;
292  p_ios_ += (acc_ios_++) ? diff : 0.0;
293  p_begin_io_ = now;
294  }
295 }
296 
297 void stats::p_write_finished(const double now)
298 {
299  {
300  std::unique_lock<std::mutex> write_lock(write_mutex_);
301 
302  const double diff = now - p_begin_write_;
303  p_begin_write_ = now;
304  p_writes_ += (acc_writes_--) ? diff : 0.0;
305  }
306  {
307  std::unique_lock<std::mutex> io_lock(io_mutex_);
308 
309  const double diff = now - p_begin_io_;
310  p_ios_ += (acc_ios_--) ? diff : 0.0;
311  p_begin_io_ = now;
312  }
313 }
314 
315 void stats::p_read_started(const double now)
316 {
317  {
318  std::unique_lock<std::mutex> read_lock(read_mutex_);
319 
320  const double diff = now - p_begin_read_;
321  p_begin_read_ = now;
322  p_reads_ += (acc_reads_++) ? diff : 0.0;
323  }
324  {
325  std::unique_lock<std::mutex> io_lock(io_mutex_);
326 
327  const double diff = now - p_begin_io_;
328  p_ios_ += (acc_ios_++) ? diff : 0.0;
329  p_begin_io_ = now;
330  }
331 }
332 
333 void stats::p_read_finished(const double now)
334 {
335  {
336  std::unique_lock<std::mutex> read_lock(read_mutex_);
337 
338  const double diff = now - p_begin_read_;
339  p_begin_read_ = now;
340  p_reads_ += (acc_reads_--) ? diff : 0.0;
341  }
342  {
343  std::unique_lock<std::mutex> io_lock(io_mutex_);
344 
345  const double diff = now - p_begin_io_;
346  p_ios_ += (acc_ios_--) ? diff : 0.0;
347  p_begin_io_ = now;
348  }
349 }
350 
351 file_stats* stats::create_file_stats(unsigned int device_id)
352 {
353  std::unique_lock<std::mutex> lock(list_mutex_);
354  auto it = std::lower_bound(
355  file_stats_list_.begin(), file_stats_list_.end(),
356  device_id, [](const file_stats& fs, unsigned id) {
357  return fs.get_device_id() < id;
358  }
359  );
360  if (it != file_stats_list_.end() && it->get_device_id())
361  return &*it;
362 
363  file_stats_list_.emplace(it, /* construction: */ device_id);
364  return &file_stats_list_.back();
365 }
366 
367 std::vector<file_stats_data> stats::deepcopy_file_stats_data_list() const
368 {
369  std::unique_lock<std::mutex> lock(list_mutex_);
370  return {
371  file_stats_list_.cbegin(), file_stats_list_.cend()
372  };
373 }
374 
375 std::ostream& operator << (std::ostream& o, const stats& s)
376 {
377  o << stats_data(s);
378  return o;
379 }
380 
381 /******************************************************************************/
382 // stats_data
383 
384 template <typename T, typename Functor>
385 T stats_data::fetch_sum(const Functor& get_value) const
386 {
387  return std::accumulate(
388  file_stats_data_list_.cbegin(), file_stats_data_list_.cend(), T(0),
389  [get_value](T sum, const auto& x) { return sum + get_value(x); });
390 }
391 
392 template <typename T>
393 template <typename Functor>
395  const std::vector<file_stats_data>& fs, const Functor& get_value)
396 {
397  values_per_device.reserve(fs.size());
398  for (const auto& f : fs) {
399  values_per_device.emplace_back(get_value(f), f.get_device_id());
400  }
401 
402  std::sort(
403  values_per_device.begin(), values_per_device.end(),
404  [](std::pair<T, unsigned> a, std::pair<T, unsigned> b) {
405  return a.first < b.first;
406  }
407  );
408 
409  if (values_per_device.size() != 0)
410  {
411  min = values_per_device.front().first;
412  max = values_per_device.back().first;
413 
414  const size_t mid = values_per_device.size() / 2;
415  median =
416  (values_per_device.size() % 2)
417  ? values_per_device[mid].first
418  : (values_per_device[mid - 1].first + values_per_device[mid].first) / 2.0;
419 
420  total = std::accumulate(
421  values_per_device.cbegin(), values_per_device.cend(), T(0),
422  [](T sum, const auto& x) { return sum + x.first; });
423 
424  average = static_cast<double>(total) / values_per_device.size();
425  }
426  else
427  {
428  min = std::numeric_limits<T>::quiet_NaN();
429  max = std::numeric_limits<T>::quiet_NaN();
430  median = std::numeric_limits<T>::quiet_NaN();
431  total = std::numeric_limits<T>::quiet_NaN();
432  average = std::numeric_limits<T>::quiet_NaN();
433  }
434 }
435 
436 struct FileStatsDataCompare {
437  long long operator () (const file_stats_data& a, const file_stats_data& b) const
438  {
439  return static_cast<long long>(a.get_device_id())
440  - static_cast<long long>(b.get_device_id());
441  }
442 };
443 
445 {
446  stats_data s;
447 
449  file_stats_data_list_.cbegin(), file_stats_data_list_.cend(),
450  a.file_stats_data_list_.cbegin(), a.file_stats_data_list_.cend(),
451  std::back_inserter(s.file_stats_data_list_),
452  FileStatsDataCompare(),
453  [](const file_stats_data& a, const file_stats_data& b) {
454  return a + b;
455  }
456  );
457 
458  s.p_reads_ = p_reads_ + a.p_reads_;
459  s.p_writes_ = p_writes_ + a.p_writes_;
460  s.p_ios_ = p_ios_ + a.p_ios_;
461  s.t_wait = t_wait + a.t_wait;
462  s.t_wait_read_ = t_wait_read_ + a.t_wait_read_;
463  s.t_wait_write_ = t_wait_write_ + a.t_wait_write_;
464  s.elapsed_ = elapsed_ + a.elapsed_;
465  return s;
466 }
467 
469 {
470  stats_data s;
471 
473  file_stats_data_list_.cbegin(), file_stats_data_list_.cend(),
474  a.file_stats_data_list_.cbegin(), a.file_stats_data_list_.cend(),
475  std::back_inserter(s.file_stats_data_list_),
476  FileStatsDataCompare(),
477  [](const file_stats_data& a, const file_stats_data& b) {
478  return a - b;
479  }
480  );
481 
482  s.p_reads_ = p_reads_ - a.p_reads_;
483  s.p_writes_ = p_writes_ - a.p_writes_;
484  s.p_ios_ = p_ios_ - a.p_ios_;
485  s.t_wait = t_wait - a.t_wait;
486  s.t_wait_read_ = t_wait_read_ - a.t_wait_read_;
487  s.t_wait_write_ = t_wait_write_ - a.t_wait_write_;
488  s.elapsed_ = elapsed_ - a.elapsed_;
489  return s;
490 }
491 
492 size_t stats_data::num_files() const
493 {
494  return file_stats_data_list_.size();
495 }
496 
498 {
499  return fetch_sum<unsigned>(
500  [](const file_stats_data& fsd) { return fsd.get_read_count(); });
501 }
502 
504 {
505  return {
506  file_stats_data_list_, [](const file_stats_data& fsd) {
507  return fsd.get_read_count();
508  }
509  };
510 }
511 
513 {
514  return fetch_sum<unsigned>(
515  [](const file_stats_data& fsd) { return fsd.get_write_count(); });
516 }
517 
519 {
520  return {
521  file_stats_data_list_, [](const file_stats_data& fsd) {
522  return fsd.get_write_count();
523  }
524  };
525 }
526 
528 {
529  return fetch_sum<external_size_type>(
530  [](const file_stats_data& fsd) { return fsd.get_read_bytes(); });
531 }
532 
535 {
536  return {
537  file_stats_data_list_, [](const file_stats_data& fsd) {
538  return fsd.get_read_bytes();
539  }
540  };
541 }
542 
544 {
545  return fetch_sum<external_size_type>(
546  [](const file_stats_data& fsd) { return fsd.get_write_bytes(); });
547 }
548 
551 {
552  return {
553  file_stats_data_list_, [](const file_stats_data& fsd) {
554  return fsd.get_write_bytes();
555  }
556  };
557 }
558 
560 {
561  return fetch_sum<double>(
562  [](const file_stats_data& fsd) { return fsd.get_read_time(); });
563 }
564 
566 {
567  return {
568  file_stats_data_list_, [](const file_stats_data& fsd) {
569  return fsd.get_read_time();
570  }
571  };
572 }
573 
575 {
576  return fetch_sum<double>(
577  [](const file_stats_data& fsd) { return fsd.get_write_time(); });
578 }
579 
581 {
582  return {
583  file_stats_data_list_, [](const file_stats_data& fsd) {
584  return fsd.get_write_time();
585  }
586  };
587 }
588 
590 {
591  return p_reads_;
592 }
593 
595 {
596  return p_writes_;
597 }
598 
600 {
601  return p_ios_;
602 }
603 
605 {
606  return {
607  file_stats_data_list_, [](const file_stats_data& fsd) {
608  return static_cast<double>(fsd.get_read_bytes()) / fsd.get_read_time();
609  }
610  };
611 }
612 
614 {
615  return {
616  file_stats_data_list_, [this](const file_stats_data& fsd) {
617  return static_cast<double>(fsd.get_read_bytes()) / p_reads_;
618  }
619  };
620 }
621 
623 {
624  return {
625  file_stats_data_list_, [](const file_stats_data& fsd) {
626  return static_cast<double>(fsd.get_write_bytes()) / fsd.get_write_time();
627  }
628  };
629 }
630 
632 {
633  return {
634  file_stats_data_list_, [this](const file_stats_data& fsd) {
635  return static_cast<double>(fsd.get_write_bytes()) / p_writes_;
636  }
637  };
638 }
639 
641 {
642  return {
643  file_stats_data_list_, [this](const file_stats_data& fsd) {
644  return static_cast<double>(fsd.get_read_bytes() + fsd.get_write_bytes()) / p_ios_;
645  }
646  };
647 }
648 
650 {
651  return t_wait;
652 }
653 
655 {
656  return t_wait_read_;
657 }
658 
660 {
661  return t_wait_write_;
662 }
663 
664 void stats_data::to_ostream(std::ostream& o, const std::string line_prefix) const
665 {
666  constexpr double one_mib = 1024.0 * 1024;
667 
668  o << "I/O statistics\n" << line_prefix;
669 
670  size_t nf = num_files();
671  if (nf != 1) {
672  o << " number of disks/files : "
673  << nf << "\n" << line_prefix;
674  }
675 
676  const auto read_bytes_summary = get_read_bytes_summary();
677  const auto write_bytes_summary = get_write_bytes_summary();
678 
679  const auto read_speed_summary = get_read_speed_summary();
680  const auto pread_speed_summary = get_pread_speed_summary();
681  const auto write_speed_summary = get_write_speed_summary();
682  const auto pwrite_speed_summary = get_pwrite_speed_summary();
683  const auto pio_speed_summary = get_pio_speed_summary();
684 
685  o << " total number of reads : "
686  << add_IEC_binary_multiplier(get_read_count()) << "\n" << line_prefix;
687  o << " average block size (read) : "
688  << add_IEC_binary_multiplier(get_read_count() ? get_read_bytes() / get_read_count() : 0, "B")
689  << "\n" << line_prefix;
690  o << " number of bytes read from disks : "
691  << add_IEC_binary_multiplier(get_read_bytes(), "B") << "\n" << line_prefix;
692  o << " time spent in serving all read requests : "
693  << get_read_time() << " s"
694  << " @ " << (static_cast<double>(get_read_bytes()) / one_mib / get_read_time()) << " MiB/s";
695  if (nf > 1) {
696  o << " (min: " << read_speed_summary.min / one_mib << " MiB/s, "
697  << "max: " << read_speed_summary.max / one_mib << " MiB/s)";
698  }
699  o << "\n" << line_prefix;
700  o << " time spent in reading (parallel read time) : "
701  << get_pread_time() << " s"
702  << " @ " << (static_cast<double>(get_read_bytes()) / one_mib / get_pread_time()) << " MiB/s"
703  << "\n" << line_prefix;
704  if (nf > 1) {
705  o << " reading speed per file : "
706  << "min: " << pread_speed_summary.min / one_mib << " MiB/s, "
707  << "median: " << pread_speed_summary.median / one_mib << " MiB/s, "
708  << "max: " << pread_speed_summary.max / one_mib << " MiB/s"
709  << "\n" << line_prefix;
710  }
711 
712  o << " total number of writes : "
713  << add_IEC_binary_multiplier(get_write_count()) << "\n" << line_prefix
714  << " average block size (write) : "
715  << add_IEC_binary_multiplier(get_write_count() ? get_write_bytes() / get_write_count() : 0, "B") << "\n" << line_prefix
716  << " number of bytes written to disks : "
717  << add_IEC_binary_multiplier(get_write_bytes(), "B") << "\n" << line_prefix
718  << " time spent in serving all write requests : "
719  << get_write_time() << " s"
720  << " @ " << (static_cast<double>(get_write_bytes()) / one_mib / get_write_time()) << " MiB/s";
721 
722  if (nf > 1) {
723  o << " (min: " << write_speed_summary.min / one_mib << " MiB/s, "
724  << "max: " << write_speed_summary.max / one_mib << " MiB/s)";
725  }
726  o << "\n" << line_prefix;
727 
728  o << " time spent in writing (parallel write time): " << get_pwrite_time() << " s"
729  << " @ " << (static_cast<double>(get_write_bytes()) / one_mib / get_pwrite_time()) << " MiB/s"
730  << "\n" << line_prefix;
731  if (nf > 1) {
732  o << " parallel write speed per file : "
733  << "min: " << pwrite_speed_summary.min / one_mib << " MiB/s, "
734  << "median: " << pwrite_speed_summary.median / one_mib << " MiB/s, "
735  << "max: " << pwrite_speed_summary.max / one_mib << " MiB/s"
736  << "\n" << line_prefix;
737  }
738 
739  o << " time spent in I/O (parallel I/O time) : " << get_pio_time() << " s"
740  << " @ " << (static_cast<double>((get_read_bytes()) + get_write_bytes()) / one_mib / get_pio_time()) << " MiB/s"
741  << "\n" << line_prefix;
742  if (nf > 1) {
743  o << " parallel I/O speed per file : "
744  << "min: " << pio_speed_summary.min / one_mib << " MiB/s, "
745  << "median: " << pio_speed_summary.median / one_mib << " MiB/s, "
746  << "max: " << pio_speed_summary.max / one_mib << " MiB/s"
747  << "\n" << line_prefix;
748  }
749 #ifndef FOXXLL_DO_NOT_COUNT_WAIT_TIME
750  o << " I/O wait time : "
751  << get_io_wait_time() << " s\n" << line_prefix;
752  if (get_wait_read_time() != 0.0)
753  o << " I/O wait4read time : "
754  << get_wait_read_time() << " s\n" << line_prefix;
755  if (get_wait_write_time() != 0.0)
756  o << " I/O wait4write time : "
757  << get_wait_write_time() << " s\n" << line_prefix;
758 #endif
759  o << " Time since the last reset : "
760  << get_elapsed_time() << " s";
761 
762  if (pio_speed_summary.min / pio_speed_summary.max < 0.5 ||
763  pread_speed_summary.min / pread_speed_summary.max < 0.5 ||
764  pwrite_speed_summary.min / pwrite_speed_summary.max < 0.5)
765  {
766  o << "\n" << line_prefix
767  << "WARNING: Slow disk(s) detected.\n" << line_prefix
768  << " Reading: ";
769  o << pread_speed_summary.values_per_device.front().second
770  << "@ " << pread_speed_summary.values_per_device.front().first / one_mib << " MiB/s";
771  for (int i = 1; pread_speed_summary.values_per_device[i].first / pread_speed_summary.values_per_device.back().first < 0.5; ++i)
772  {
773  o << ", " << pread_speed_summary.values_per_device[i].second
774  << "@ " << pread_speed_summary.values_per_device[i].first / one_mib << " MiB/s";
775  }
776  o << "\n" << line_prefix
777  << " Writing: "
778  << pwrite_speed_summary.values_per_device.front().second
779  << "@ " << pwrite_speed_summary.values_per_device.front().first / one_mib << " MiB/s";
780  for (int i = 1; pwrite_speed_summary.values_per_device[i].first / pwrite_speed_summary.values_per_device.back().first < 0.5; ++i)
781  {
782  o << ", " << pwrite_speed_summary.values_per_device[i].second
783  << "@ " << pwrite_speed_summary.values_per_device[i].first / one_mib << " MiB/s";
784  }
785  }
786 
787  if (static_cast<double>(read_bytes_summary.min) / read_bytes_summary.max < 0.5 ||
788  static_cast<double>(write_bytes_summary.min) / write_bytes_summary.max < 0.5)
789  {
790  o << "\n" << line_prefix <<
791  "WARNING: Bad load balancing.\n" << line_prefix
792  << " Smallest read load on disk "
793  << read_bytes_summary.values_per_device.front().second
794  << " @ " << add_IEC_binary_multiplier(read_bytes_summary.values_per_device.front().first, "B")
795  << "\n" << line_prefix
796  << " Biggest read load on disk "
797  << read_bytes_summary.values_per_device.back().second
798  << " @ " << add_IEC_binary_multiplier(read_bytes_summary.values_per_device.back().first, "B")
799  << "\n" << line_prefix
800  << " Smallest write load on disk "
801  << write_bytes_summary.values_per_device.front().second
802  << " @ " << add_IEC_binary_multiplier(write_bytes_summary.values_per_device.front().first, "B")
803  << "\n" << line_prefix
804  << " Biggest write load on disk "
805  << write_bytes_summary.values_per_device.back().second
806  << " @ " << add_IEC_binary_multiplier(write_bytes_summary.values_per_device.back().first, "B")
807  << "\n" << line_prefix;
808  }
809 
810  o << std::endl;
811 }
812 
814 {
815  const auto result = foxxll::stats_data(*foxxll::stats::get_instance()) - begin_;
816 
817  std::ostringstream ss;
818 
819  ss << (message_.empty() ? "" : "Finished ") << message_ << ". ";
820 
821  if (bytes_) {
822  const auto bps = static_cast<double>(bytes_) / result.get_elapsed_time();
823  ss << "Processed " << tlx::format_iec_units(bytes_) << "B"
824  << " @ " << tlx::format_iec_units(static_cast<uint64_t>(bps)) << "B/s. ";
825  }
826 
827  result.to_ostream(ss, key_);
828 
829  TLX_LOG1 << ss.str();
830 }
831 
832 } // namespace foxxll
833 
834 /**************************************************************************/
std::mutex io_mutex_
Definition: iostats.hpp:358
std::mutex write_mutex_
Definition: iostats.hpp:358
unsigned get_device_id() const
Definition: iostats.hpp:281
double get_elapsed_time() const
Definition: iostats.hpp:620
double get_read_time() const
Definition: iostats.cpp:559
double get_pwrite_time() const
Definition: iostats.cpp:594
double get_pwrite_time() const
Definition: iostats.hpp:453
stats_data::summary< double > get_write_speed_summary() const
Definition: iostats.cpp:622
static uint_pair max()
return an uint_pair instance containing the largest value possible
Definition: uint_types.hpp:226
double get_pread_time() const
Definition: iostats.hpp:446
external_size_type write_bytes_
Definition: iostats.hpp:53
int acc_reads_
number of requests, participating in parallel operation
Definition: iostats.hpp:60
void to_ostream(std::ostream &o, const std::string line_prefix="") const
Definition: iostats.cpp:664
external_size_type write_bytes_
Definition: iostats.hpp:255
double p_begin_wait_write_
Definition: iostats.hpp:354
void report() const
print out relative stats via LOG
Definition: iostats.cpp:813
int acc_wait_read_
Definition: iostats.hpp:356
std::mutex write_mutex_
Definition: iostats.hpp:62
void p_read_finished(double now)
Definition: iostats.cpp:333
double T
unsigned read_count_
number of operations
Definition: iostats.hpp:253
double p_begin_read_
start time of parallel operation
Definition: iostats.hpp:57
void write_started(const size_t size_, double now=0.0)
Definition: iostats.cpp:44
std::vector< file_stats_data > deepcopy_file_stats_data_list() const
return list of file&#39;s stats data (deeply copied from each file_stats)
Definition: iostats.cpp:367
summary(const std::vector< file_stats_data > &fs, const Functor &get_value)
Definition: iostats.cpp:394
double p_begin_write_
Definition: iostats.hpp:57
T fetch_sum(const Functor &get_value) const
aggregator
Definition: iostats.cpp:385
std::mutex read_mutex_
Definition: iostats.hpp:62
double p_begin_io_
Definition: iostats.hpp:340
external_size_type get_read_bytes() const
Definition: iostats.cpp:527
std::mutex list_mutex_
Definition: iostats.hpp:330
stats_data::summary< double > get_pio_speed_summary() const
Definition: iostats.cpp:640
std::mutex wait_mutex_
Definition: iostats.hpp:358
void read_op_finished(const size_t size_, double duration)
Definition: iostats.cpp:141
stats_data::summary< double > get_pwrite_speed_summary() const
Definition: iostats.cpp:631
OutputIterator merge_combine(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Comparator cmp=Comparator(), Combine combine=Combine())
Merge two sorted ranges and add all items comparing equal.
stats_data::summary< double > get_read_speed_summary() const
Definition: iostats.cpp:604
void p_write_finished(double now)
Definition: iostats.cpp:297
const unsigned device_id_
associated device id
Definition: iostats.hpp:48
void write_canceled(const size_t size_)
Definition: iostats.cpp:62
size_t num_files() const
Returns the number of file_stats_data objects.
Definition: iostats.cpp:492
double p_ios_
Definition: iostats.hpp:339
void write_finished()
Definition: iostats.cpp:73
stats_data::summary< double > get_write_time_summary() const
Definition: iostats.cpp:580
double get_wait_read_time() const
Definition: iostats.hpp:434
double p_reads_
seconds spent in parallel io
Definition: iostats.hpp:489
stats_data::summary< external_size_type > get_write_bytes_summary() const
Definition: iostats.cpp:550
static double timestamp()
Returns number of seconds since the epoch, high resolution.
Definition: timer.hpp:36
int acc_wait_write_
Definition: iostats.hpp:356
void p_read_started(double now)
Definition: iostats.cpp:315
double get_wait_write_time() const
Definition: iostats.cpp:659
stats_data operator+(const stats_data &a) const
Definition: iostats.cpp:444
double p_writes_
Definition: iostats.hpp:335
void wait_started(wait_op_type wait_op_)
Definition: iostats.cpp:217
friend std::ostream & operator<<(std::ostream &o, const stats &s)
Definition: iostats.cpp:375
double read_time_
seconds spent in operations
Definition: iostats.hpp:257
unsigned get_write_count() const
Definition: iostats.cpp:512
file_stats_data operator+(const file_stats_data &a) const
Definition: iostats.cpp:153
external_size_type get_write_bytes() const
Definition: iostats.cpp:543
double p_wait_write_
Definition: iostats.hpp:353
double write_time_
Definition: iostats.hpp:55
double p_wait_read_
Definition: iostats.hpp:351
list x
Definition: gen_data.py:39
file_stats(unsigned int device_id)
construct zero initialized
Definition: iostats.cpp:35
double t_wait
seconds spent waiting for completion of I/O operations
Definition: iostats.hpp:492
static std::string add_IEC_binary_multiplier(const external_size_type number, const std::string &unit="")
Definition: iostats.hpp:643
unsigned write_count_
Definition: iostats.hpp:51
double p_begin_read_
start time of parallel operation
Definition: iostats.hpp:337
void read_started(const size_t size_, double now=0.0)
Definition: iostats.cpp:97
unsigned device_id_
device id
Definition: iostats.hpp:251
std::vector< file_stats_data > file_stats_data_list_
list of individual file statistics.
Definition: iostats.hpp:498
std::list< file_stats > file_stats_list_
Definition: iostats.hpp:328
FOXXLL library namespace
std::basic_string< char, std::char_traits< char >, Allocator< char > > string
string with Manager tracking
Definition: allocator.hpp:220
void p_write_started(double now)
Definition: iostats.cpp:279
stats_data::summary< unsigned > get_write_count_summary() const
Definition: iostats.cpp:518
double get_write_time() const
Definition: iostats.cpp:574
stats_data::summary< unsigned > get_read_count_summary() const
Definition: iostats.cpp:503
static instance_pointer get_instance()
return instance or create base instance if empty
Definition: singleton.hpp:41
unsigned get_read_count() const
Definition: iostats.cpp:497
stats_data::summary< double > get_pread_speed_summary() const
Definition: iostats.cpp:613
double get_wait_write_time() const
Definition: iostats.hpp:439
double p_begin_wait_
Definition: iostats.hpp:350
external_size_type read_bytes_
number of bytes read/written
Definition: iostats.hpp:53
static uint_pair min()
return an uint_pair instance containing the smallest value possible
Definition: uint_types.hpp:217
stats_data operator-(const stats_data &a) const
Definition: iostats.cpp:468
unsigned read_count_
number of operations: read/write
Definition: iostats.hpp:51
double p_reads_
seconds spent in parallel operations
Definition: iostats.hpp:335
double get_wait_read_time() const
Definition: iostats.cpp:654
stats_data::summary< double > get_read_time_summary() const
Definition: iostats.cpp:565
#define FOXXLL_THROW_IF(expr, exception_type, error_message)
Throws exception_type if (expr) with "Error in [function] : [error_message]".
double p_begin_wait_read_
Definition: iostats.hpp:352
void read_finished()
Definition: iostats.cpp:126
std::mutex read_mutex_
Definition: iostats.hpp:358
double t_wait_write_
Definition: iostats.hpp:493
void read_canceled(const size_t size_)
Definition: iostats.cpp:115
void wait_finished(wait_op_type wait_op_)
Definition: iostats.cpp:244
stats()
private construction from singleton
Definition: iostats.cpp:196
#define TLX_LOG1
Definition: core.hpp:145
stats_data::summary< external_size_type > get_read_bytes_summary() const
Definition: iostats.cpp:534
double get_pio_time() const
Definition: iostats.cpp:599
double get_io_wait_time() const
Definition: iostats.hpp:429
double get_io_wait_time() const
Definition: iostats.cpp:649
void write_op_finished(const size_t size_, double duration)
Definition: iostats.cpp:88
double p_waits_
Definition: iostats.hpp:349
external_size_type read_bytes_
number of bytes read/written
Definition: iostats.hpp:255
double read_time_
seconds spent in operations
Definition: iostats.hpp:55
double t_wait_read_
Definition: iostats.hpp:351
double p_begin_write_
Definition: iostats.hpp:337
file_stats_data operator-(const file_stats_data &a) const
Definition: iostats.cpp:173
std::string format_iec_units(uint64_t number, int precision=3)
Format number as something like 1 TiB.
double t_waits_
Definition: iostats.hpp:349
uint64_t external_size_type
Definition: types.hpp:27
double get_pread_time() const
Definition: iostats.cpp:589
double t_wait_write_
Definition: iostats.hpp:353
file_stats * create_file_stats(unsigned device_id)
Definition: iostats.cpp:351
double get_pio_time() const
Definition: iostats.hpp:460