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)
103 std::unique_lock<std::mutex> read_lock(
read_mutex_);
118 std::unique_lock<std::mutex> read_lock(
read_mutex_);
131 std::unique_lock<std::mutex> read_lock(
read_mutex_);
143 std::unique_lock<std::mutex> write_lock(
read_mutex_);
157 "foxxll::file_stats_data objects do not belong to the same file/disk" 177 "foxxll::file_stats_data objects do not belong to the same file/disk" 198 p_reads_(0.0), p_writes_(0.0),
206 t_waits_(0.0), p_waits_(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),
213 acc_wait_read_(0.0), acc_wait_write_(0.0)
216 #ifndef FOXXLL_DO_NOT_COUNT_WAIT_TIME 221 std::unique_lock<std::mutex> wait_lock(
wait_mutex_);
231 p_begin_wait_read_ = now;
238 p_begin_wait_write_ = now;
248 std::unique_lock<std::mutex> wait_lock(
wait_mutex_);
258 p_begin_wait_read_ = now;
264 p_begin_wait_write_ = now;
267 #ifdef FOXXLL_WAIT_LOG_ENABLED 270 << (now - last_reset) <<
"\t" 285 p_begin_write_ = now;
289 std::unique_lock<std::mutex> io_lock(
io_mutex_);
303 p_begin_write_ = now;
307 std::unique_lock<std::mutex> io_lock(
io_mutex_);
318 std::unique_lock<std::mutex> read_lock(
read_mutex_);
325 std::unique_lock<std::mutex> io_lock(
io_mutex_);
336 std::unique_lock<std::mutex> read_lock(
read_mutex_);
343 std::unique_lock<std::mutex> io_lock(
io_mutex_);
354 auto it = std::lower_bound(
356 device_id, [](
const file_stats& fs,
unsigned id) {
357 return fs.get_device_id() < id;
384 template <
typename T,
typename Functor>
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); });
392 template <
typename T>
393 template <
typename Functor>
395 const std::vector<file_stats_data>& fs,
const Functor& get_value)
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());
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;
409 if (values_per_device.size() != 0)
411 min = values_per_device.front().first;
412 max = values_per_device.back().first;
414 const size_t mid = values_per_device.size() / 2;
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;
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; });
424 average =
static_cast<double>(total) / values_per_device.size();
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();
436 struct FileStatsDataCompare {
449 file_stats_data_list_.cbegin(), file_stats_data_list_.cend(),
452 FileStatsDataCompare(),
461 s.
t_wait = t_wait + a.t_wait;
473 file_stats_data_list_.cbegin(), file_stats_data_list_.cend(),
476 FileStatsDataCompare(),
485 s.
t_wait = t_wait - a.t_wait;
494 return file_stats_data_list_.size();
499 return fetch_sum<unsigned>(
507 return fsd.get_read_count();
514 return fetch_sum<unsigned>(
522 return fsd.get_write_count();
529 return fetch_sum<external_size_type>(
538 return fsd.get_read_bytes();
545 return fetch_sum<external_size_type>(
554 return fsd.get_write_bytes();
561 return fetch_sum<double>(
569 return fsd.get_read_time();
576 return fetch_sum<double>(
584 return fsd.get_write_time();
608 return static_cast<double>(fsd.get_read_bytes()) / fsd.get_read_time();
617 return static_cast<double>(fsd.get_read_bytes()) /
p_reads_;
626 return static_cast<double>(fsd.get_write_bytes()) / fsd.get_write_time();
635 return static_cast<double>(fsd.get_write_bytes()) /
p_writes_;
644 return static_cast<double>(fsd.get_read_bytes() + fsd.get_write_bytes()) /
p_ios_;
666 constexpr
double one_mib = 1024.0 * 1024;
668 o <<
"I/O statistics\n" << line_prefix;
670 size_t nf = num_files();
672 o <<
" number of disks/files : " 673 << nf <<
"\n" << line_prefix;
676 const auto read_bytes_summary = get_read_bytes_summary();
677 const auto write_bytes_summary = get_write_bytes_summary();
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();
685 o <<
" total number of reads : " 687 o <<
" average block size (read) : " 689 <<
"\n" << line_prefix;
690 o <<
" number of bytes read from disks : " 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";
696 o <<
" (min: " << read_speed_summary.min / one_mib <<
" MiB/s, " 697 <<
"max: " << read_speed_summary.max / one_mib <<
" MiB/s)";
699 o <<
"\n" << line_prefix;
700 o <<
" time spent in reading (parallel read time) : " 702 <<
" @ " << (
static_cast<double>(get_read_bytes()) / one_mib /
get_pread_time()) <<
" MiB/s" 703 <<
"\n" << line_prefix;
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;
712 o <<
" total number of writes : " 714 <<
" average block size (write) : " 716 <<
" number of bytes written to disks : " 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";
723 o <<
" (min: " << write_speed_summary.min / one_mib <<
" MiB/s, " 724 <<
"max: " << write_speed_summary.max / one_mib <<
" MiB/s)";
726 o <<
"\n" << line_prefix;
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;
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;
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;
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;
749 #ifndef FOXXLL_DO_NOT_COUNT_WAIT_TIME 750 o <<
" I/O wait time : " 753 o <<
" I/O wait4read time : " 756 o <<
" I/O wait4write time : " 759 o <<
" Time since the last reset : " 760 << get_elapsed_time() <<
" s";
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)
766 o <<
"\n" << line_prefix
767 <<
"WARNING: Slow disk(s) detected.\n" << line_prefix
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)
773 o <<
", " << pread_speed_summary.values_per_device[i].second
774 <<
"@ " << pread_speed_summary.values_per_device[i].first / one_mib <<
" MiB/s";
776 o <<
"\n" << line_prefix
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)
782 o <<
", " << pwrite_speed_summary.values_per_device[i].second
783 <<
"@ " << pwrite_speed_summary.values_per_device[i].first / one_mib <<
" MiB/s";
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)
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
795 <<
"\n" << line_prefix
796 <<
" Biggest read load on disk " 797 << read_bytes_summary.values_per_device.back().second
799 <<
"\n" << line_prefix
800 <<
" Smallest write load on disk " 801 << write_bytes_summary.values_per_device.front().second
803 <<
"\n" << line_prefix
804 <<
" Biggest write load on disk " 805 << write_bytes_summary.values_per_device.back().second
807 <<
"\n" << line_prefix;
817 std::ostringstream ss;
819 ss << (message_.empty() ?
"" :
"Finished ") << message_ <<
". ";
827 result.to_ostream(ss, key_);
unsigned get_device_id() const
double get_elapsed_time() const
double get_read_time() const
double get_pwrite_time() const
double get_pwrite_time() const
stats_data::summary< double > get_write_speed_summary() const
static uint_pair max()
return an uint_pair instance containing the largest value possible
double get_pread_time() const
external_size_type write_bytes_
int acc_reads_
number of requests, participating in parallel operation
void to_ostream(std::ostream &o, const std::string line_prefix="") const
external_size_type write_bytes_
double p_begin_wait_write_
void report() const
print out relative stats via LOG
void p_read_finished(double now)
unsigned read_count_
number of operations
double p_begin_read_
start time of parallel operation
void write_started(const size_t size_, double now=0.0)
std::vector< file_stats_data > deepcopy_file_stats_data_list() const
return list of file's stats data (deeply copied from each file_stats)
summary(const std::vector< file_stats_data > &fs, const Functor &get_value)
T fetch_sum(const Functor &get_value) const
aggregator
external_size_type get_read_bytes() const
stats_data::summary< double > get_pio_speed_summary() const
void read_op_finished(const size_t size_, double duration)
stats_data::summary< double > get_pwrite_speed_summary() const
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
void p_write_finished(double now)
const unsigned device_id_
associated device id
void write_canceled(const size_t size_)
size_t num_files() const
Returns the number of file_stats_data objects.
stats_data::summary< double > get_write_time_summary() const
double get_wait_read_time() const
double p_reads_
seconds spent in parallel io
stats_data::summary< external_size_type > get_write_bytes_summary() const
static double timestamp()
Returns number of seconds since the epoch, high resolution.
void p_read_started(double now)
double get_wait_write_time() const
stats_data operator+(const stats_data &a) const
void wait_started(wait_op_type wait_op_)
friend std::ostream & operator<<(std::ostream &o, const stats &s)
double read_time_
seconds spent in operations
unsigned get_write_count() const
file_stats_data operator+(const file_stats_data &a) const
external_size_type get_write_bytes() const
file_stats(unsigned int device_id)
construct zero initialized
double t_wait
seconds spent waiting for completion of I/O operations
static std::string add_IEC_binary_multiplier(const external_size_type number, const std::string &unit="")
double p_begin_read_
start time of parallel operation
void read_started(const size_t size_, double now=0.0)
unsigned device_id_
device id
std::vector< file_stats_data > file_stats_data_list_
list of individual file statistics.
std::list< file_stats > file_stats_list_
std::basic_string< char, std::char_traits< char >, Allocator< char > > string
string with Manager tracking
void p_write_started(double now)
stats_data::summary< unsigned > get_write_count_summary() const
double get_write_time() const
stats_data::summary< unsigned > get_read_count_summary() const
static instance_pointer get_instance()
return instance or create base instance if empty
unsigned get_read_count() const
stats_data::summary< double > get_pread_speed_summary() const
double get_wait_write_time() const
external_size_type read_bytes_
number of bytes read/written
static uint_pair min()
return an uint_pair instance containing the smallest value possible
stats_data operator-(const stats_data &a) const
unsigned read_count_
number of operations: read/write
double p_reads_
seconds spent in parallel operations
double get_wait_read_time() const
stats_data::summary< double > get_read_time_summary() const
#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_
void read_canceled(const size_t size_)
void wait_finished(wait_op_type wait_op_)
stats()
private construction from singleton
stats_data::summary< external_size_type > get_read_bytes_summary() const
double get_pio_time() const
double get_io_wait_time() const
double get_io_wait_time() const
void write_op_finished(const size_t size_, double duration)
external_size_type read_bytes_
number of bytes read/written
double read_time_
seconds spent in operations
file_stats_data operator-(const file_stats_data &a) const
std::string format_iec_units(uint64_t number, int precision=3)
Format number as something like 1 TiB.
uint64_t external_size_type
double get_pread_time() const
file_stats * create_file_stats(unsigned device_id)
double get_pio_time() const