Stxxl
1.4.0
|
00001 /*************************************************************************** 00002 * include/stxxl/bits/io/iostats.h 00003 * 00004 * Part of the STXXL. See http://stxxl.sourceforge.net 00005 * 00006 * Copyright (C) 2002-2004 Roman Dementiev <dementiev@mpi-sb.mpg.de> 00007 * Copyright (C) 2008-2010 Andreas Beckmann <beckmann@cs.uni-frankfurt.de> 00008 * Copyright (C) 2009, 2010 Johannes Singler <singler@kit.edu> 00009 * 00010 * Distributed under the Boost Software License, Version 1.0. 00011 * (See accompanying file LICENSE_1_0.txt or copy at 00012 * http://www.boost.org/LICENSE_1_0.txt) 00013 **************************************************************************/ 00014 00015 #ifndef STXXL_IOSTATS_HEADER 00016 #define STXXL_IOSTATS_HEADER 00017 00018 #ifndef STXXL_IO_STATS 00019 #define STXXL_IO_STATS 1 00020 #endif 00021 00022 00023 #include <iostream> 00024 00025 #include <stxxl/bits/namespace.h> 00026 #include <stxxl/bits/deprecated.h> 00027 #include <stxxl/bits/common/mutex.h> 00028 #include <stxxl/bits/common/timer.h> 00029 #include <stxxl/bits/common/types.h> 00030 #include <stxxl/bits/common/utils.h> 00031 #include <stxxl/bits/unused.h> 00032 #include <stxxl/bits/singleton.h> 00033 00034 00035 __STXXL_BEGIN_NAMESPACE 00036 00037 //! \addtogroup iolayer 00038 //! 00039 //! \{ 00040 00041 //! \brief Collects various I/O statistics 00042 //! \remarks is a singleton 00043 class stats : public singleton<stats> 00044 { 00045 friend class singleton<stats>; 00046 00047 unsigned reads, writes; // number of operations 00048 int64 volume_read, volume_written; // number of bytes read/written 00049 unsigned c_reads, c_writes; // number of cached operations 00050 int64 c_volume_read, c_volume_written; // number of bytes read/written from/to cache 00051 double t_reads, t_writes; // seconds spent in operations 00052 double p_reads, p_writes; // seconds spent in parallel operations 00053 double p_begin_read, p_begin_write; // start time of parallel operation 00054 double p_ios; // seconds spent in all parallel I/O operations (read and write) 00055 double p_begin_io; 00056 double t_waits, p_waits; // seconds spent waiting for completion of I/O operations 00057 double p_begin_wait; 00058 double t_wait_read, p_wait_read; 00059 double p_begin_wait_read; 00060 double t_wait_write, p_wait_write; 00061 double p_begin_wait_write; 00062 int acc_reads, acc_writes; // number of requests, participating in parallel operation 00063 int acc_ios; 00064 int acc_waits; 00065 int acc_wait_read, acc_wait_write; 00066 double last_reset; 00067 mutex read_mutex, write_mutex, io_mutex, wait_mutex; 00068 00069 stats(); 00070 00071 public: 00072 enum wait_op_type { 00073 WAIT_OP_ANY, 00074 WAIT_OP_READ, 00075 WAIT_OP_WRITE 00076 }; 00077 00078 class scoped_read_write_timer 00079 { 00080 typedef unsigned_type size_type; 00081 00082 bool is_write; 00083 #if STXXL_IO_STATS 00084 bool running; 00085 #endif 00086 00087 public: 00088 scoped_read_write_timer(size_type size, bool is_write = false) 00089 : is_write(is_write) 00090 #if STXXL_IO_STATS 00091 , running(false) 00092 #endif 00093 { 00094 start(size); 00095 } 00096 00097 ~scoped_read_write_timer() 00098 { 00099 stop(); 00100 } 00101 00102 void start(size_type size) 00103 { 00104 #if STXXL_IO_STATS 00105 if (!running) { 00106 running = true; 00107 if (is_write) 00108 stats::get_instance()->write_started(size); 00109 else 00110 stats::get_instance()->read_started(size); 00111 } 00112 #else 00113 STXXL_UNUSED(size); 00114 #endif 00115 } 00116 00117 void stop() 00118 { 00119 #if STXXL_IO_STATS 00120 if (running) { 00121 if (is_write) 00122 stats::get_instance()->write_finished(); 00123 else 00124 stats::get_instance()->read_finished(); 00125 running = false; 00126 } 00127 #endif 00128 } 00129 }; 00130 00131 class scoped_write_timer 00132 { 00133 typedef unsigned_type size_type; 00134 00135 #if STXXL_IO_STATS 00136 bool running; 00137 #endif 00138 00139 public: 00140 scoped_write_timer(size_type size) 00141 #if STXXL_IO_STATS 00142 : running(false) 00143 #endif 00144 { 00145 start(size); 00146 } 00147 00148 ~scoped_write_timer() 00149 { 00150 stop(); 00151 } 00152 00153 void start(size_type size) 00154 { 00155 #if STXXL_IO_STATS 00156 if (!running) { 00157 running = true; 00158 stats::get_instance()->write_started(size); 00159 } 00160 #else 00161 STXXL_UNUSED(size); 00162 #endif 00163 } 00164 00165 void stop() 00166 { 00167 #if STXXL_IO_STATS 00168 if (running) { 00169 stats::get_instance()->write_finished(); 00170 running = false; 00171 } 00172 #endif 00173 } 00174 }; 00175 00176 class scoped_read_timer 00177 { 00178 typedef unsigned_type size_type; 00179 00180 #if STXXL_IO_STATS 00181 bool running; 00182 #endif 00183 00184 public: 00185 scoped_read_timer(size_type size) 00186 #if STXXL_IO_STATS 00187 : running(false) 00188 #endif 00189 { 00190 start(size); 00191 } 00192 00193 ~scoped_read_timer() 00194 { 00195 stop(); 00196 } 00197 00198 void start(size_type size) 00199 { 00200 #if STXXL_IO_STATS 00201 if (!running) { 00202 running = true; 00203 stats::get_instance()->read_started(size); 00204 } 00205 #else 00206 STXXL_UNUSED(size); 00207 #endif 00208 } 00209 00210 void stop() 00211 { 00212 #if STXXL_IO_STATS 00213 if (running) { 00214 stats::get_instance()->read_finished(); 00215 running = false; 00216 } 00217 #endif 00218 } 00219 }; 00220 00221 class scoped_wait_timer 00222 { 00223 #ifndef STXXL_DO_NOT_COUNT_WAIT_TIME 00224 bool running; 00225 wait_op_type wait_op; 00226 #endif 00227 00228 public: 00229 scoped_wait_timer(wait_op_type wait_op, bool measure_time = true) 00230 #ifndef STXXL_DO_NOT_COUNT_WAIT_TIME 00231 : running(false), wait_op(wait_op) 00232 #endif 00233 { 00234 if (measure_time) 00235 start(); 00236 } 00237 00238 ~scoped_wait_timer() 00239 { 00240 stop(); 00241 } 00242 00243 void start() 00244 { 00245 #ifndef STXXL_DO_NOT_COUNT_WAIT_TIME 00246 if (!running) { 00247 running = true; 00248 stats::get_instance()->wait_started(wait_op); 00249 } 00250 #endif 00251 } 00252 00253 void stop() 00254 { 00255 #ifndef STXXL_DO_NOT_COUNT_WAIT_TIME 00256 if (running) { 00257 stats::get_instance()->wait_finished(wait_op); 00258 running = false; 00259 } 00260 #endif 00261 } 00262 }; 00263 00264 public: 00265 //! \brief Returns total number of reads 00266 //! \return total number of reads 00267 unsigned get_reads() const 00268 { 00269 return reads; 00270 } 00271 00272 //! \brief Returns total number of writes 00273 //! \return total number of writes 00274 unsigned get_writes() const 00275 { 00276 return writes; 00277 } 00278 00279 //! \brief Returns number of bytes read from disks 00280 //! \return number of bytes read 00281 int64 get_read_volume() const 00282 { 00283 return volume_read; 00284 } 00285 00286 //! \brief Returns number of bytes written to the disks 00287 //! \return number of bytes written 00288 int64 get_written_volume() const 00289 { 00290 return volume_written; 00291 } 00292 00293 //! \brief Returns total number of reads served from cache 00294 //! \return total number of cached reads 00295 unsigned get_cached_reads() const 00296 { 00297 return c_reads; 00298 } 00299 00300 //! \brief Returns total number of cached writes 00301 //! \return total number of cached writes 00302 unsigned get_cached_writes() const 00303 { 00304 return c_writes; 00305 } 00306 00307 //! \brief Returns number of bytes read from cache 00308 //! \return number of bytes read from cache 00309 int64 get_cached_read_volume() const 00310 { 00311 return c_volume_read; 00312 } 00313 00314 //! \brief Returns number of bytes written to the cache 00315 //! \return number of bytes written to cache 00316 int64 get_cached_written_volume() const 00317 { 00318 return c_volume_written; 00319 } 00320 00321 //! \brief Time that would be spent in read syscalls if all parallel reads were serialized. 00322 //! \return seconds spent in reading 00323 double get_read_time() const 00324 { 00325 return t_reads; 00326 } 00327 00328 //! \brief Time that would be spent in write syscalls if all parallel writes were serialized. 00329 //! \return seconds spent in writing 00330 double get_write_time() const 00331 { 00332 return t_writes; 00333 } 00334 00335 //! \brief Period of time when at least one I/O thread was executing a read. 00336 //! \return seconds spent in reading 00337 double get_pread_time() const 00338 { 00339 return p_reads; 00340 } 00341 00342 //! \brief Period of time when at least one I/O thread was executing a write. 00343 //! \return seconds spent in writing 00344 double get_pwrite_time() const 00345 { 00346 return p_writes; 00347 } 00348 00349 //! \brief Period of time when at least one I/O thread was executing a read or a write. 00350 //! \return seconds spent in I/O 00351 double get_pio_time() const 00352 { 00353 return p_ios; 00354 } 00355 00356 //! \brief I/O wait time counter 00357 //! \return number of seconds spent in I/O waiting functions 00358 //! \link request::wait request::wait \endlink, 00359 //! \c wait_any and 00360 //! \c wait_all 00361 double get_io_wait_time() const 00362 { 00363 return t_waits; 00364 } 00365 00366 double get_wait_read_time() const 00367 { 00368 return t_wait_read; 00369 } 00370 00371 double get_wait_write_time() const 00372 { 00373 return t_wait_write; 00374 } 00375 00376 //! \brief Return time of the last reset 00377 //! \return seconds passed from the last reset() 00378 double get_last_reset_time() const 00379 { 00380 return last_reset; 00381 } 00382 00383 #ifndef STXXL_IO_STATS_RESET_FORBIDDEN 00384 //! \brief Resets I/O time counters (including I/O wait counter) 00385 _STXXL_DEPRECATED(void reset()); 00386 #endif 00387 00388 //! \brief Resets I/O wait time counter 00389 _STXXL_DEPRECATED(void _reset_io_wait_time()); 00390 00391 // for library use 00392 void write_started(unsigned_type size_, double now = 0.0); 00393 void write_canceled(unsigned_type size_); 00394 void write_finished(); 00395 void write_cached(unsigned_type size_); 00396 void read_started(unsigned_type size_, double now = 0.0); 00397 void read_canceled(unsigned_type size_); 00398 void read_finished(); 00399 void read_cached(unsigned_type size_); 00400 void wait_started(wait_op_type wait_op); 00401 void wait_finished(wait_op_type wait_op); 00402 }; 00403 00404 #if !STXXL_IO_STATS 00405 inline void stats::write_started(unsigned_type size_, double now) 00406 { 00407 STXXL_UNUSED(size_); 00408 STXXL_UNUSED(now); 00409 } 00410 inline void stats::write_cached(unsigned_type size_) 00411 { 00412 STXXL_UNUSED(size_); 00413 } 00414 inline void stats::write_finished() { } 00415 inline void stats::read_started(unsigned_type size_, double now) 00416 { 00417 STXXL_UNUSED(size_); 00418 STXXL_UNUSED(now); 00419 } 00420 inline void stats::read_cached(unsigned_type size_) 00421 { 00422 STXXL_UNUSED(size_); 00423 } 00424 inline void stats::read_finished() { } 00425 #endif 00426 #ifdef STXXL_DO_NOT_COUNT_WAIT_TIME 00427 inline void stats::wait_started(wait_op_type) { } 00428 inline void stats::wait_finished(wait_op_type) { } 00429 #endif 00430 00431 00432 class stats_data 00433 { 00434 unsigned reads, writes; // number of operations 00435 int64 volume_read, volume_written; // number of bytes read/written 00436 unsigned c_reads, c_writes; // number of cached operations 00437 int64 c_volume_read, c_volume_written; // number of bytes read/written from/to cache 00438 double t_reads, t_writes; // seconds spent in operations 00439 double p_reads, p_writes; // seconds spent in parallel operations 00440 double p_ios; // seconds spent in all parallel I/O operations (read and write) 00441 double t_wait; // seconds spent waiting for completion of I/O operations 00442 double t_wait_read, t_wait_write; // 00443 double elapsed; 00444 00445 public: 00446 stats_data() : 00447 reads(0), 00448 writes(0), 00449 volume_read(0), 00450 volume_written(0), 00451 c_reads(0), 00452 c_writes(0), 00453 c_volume_read(0), 00454 c_volume_written(0), 00455 t_reads(0.0), 00456 t_writes(0.0), 00457 p_reads(0.0), 00458 p_writes(0.0), 00459 p_ios(0.0), 00460 t_wait(0.0), 00461 t_wait_read(0.0), 00462 t_wait_write(0.0), 00463 elapsed(0.0) 00464 { } 00465 00466 stats_data(const stats & s) : 00467 reads(s.get_reads()), 00468 writes(s.get_writes()), 00469 volume_read(s.get_read_volume()), 00470 volume_written(s.get_written_volume()), 00471 c_reads(s.get_cached_reads()), 00472 c_writes(s.get_cached_writes()), 00473 c_volume_read(s.get_cached_read_volume()), 00474 c_volume_written(s.get_cached_written_volume()), 00475 t_reads(s.get_read_time()), 00476 t_writes(s.get_write_time()), 00477 p_reads(s.get_pread_time()), 00478 p_writes(s.get_pwrite_time()), 00479 p_ios(s.get_pio_time()), 00480 t_wait(s.get_io_wait_time()), 00481 t_wait_read(s.get_wait_read_time()), 00482 t_wait_write(s.get_wait_write_time()), 00483 elapsed(timestamp() - s.get_last_reset_time()) 00484 { } 00485 00486 stats_data operator + (const stats_data & a) const 00487 { 00488 stats_data s; 00489 s.reads = reads + a.reads; 00490 s.writes = writes + a.writes; 00491 s.volume_read = volume_read + a.volume_read; 00492 s.volume_written = volume_written + a.volume_written; 00493 s.c_reads = c_reads + a.c_reads; 00494 s.c_writes = c_writes + a.c_writes; 00495 s.c_volume_read = c_volume_read + a.c_volume_read; 00496 s.c_volume_written = c_volume_written + a.c_volume_written; 00497 s.t_reads = t_reads + a.t_reads; 00498 s.t_writes = t_writes + a.t_writes; 00499 s.p_reads = p_reads + a.p_reads; 00500 s.p_writes = p_writes + a.p_writes; 00501 s.p_ios = p_ios + a.p_ios; 00502 s.t_wait = t_wait + a.t_wait; 00503 s.t_wait_read = t_wait_read + a.t_wait_read; 00504 s.t_wait_write = t_wait_write + a.t_wait_write; 00505 s.elapsed = elapsed + a.elapsed; 00506 return s; 00507 } 00508 00509 stats_data operator - (const stats_data & a) const 00510 { 00511 stats_data s; 00512 s.reads = reads - a.reads; 00513 s.writes = writes - a.writes; 00514 s.volume_read = volume_read - a.volume_read; 00515 s.volume_written = volume_written - a.volume_written; 00516 s.c_reads = c_reads - a.c_reads; 00517 s.c_writes = c_writes - a.c_writes; 00518 s.c_volume_read = c_volume_read - a.c_volume_read; 00519 s.c_volume_written = c_volume_written - a.c_volume_written; 00520 s.t_reads = t_reads - a.t_reads; 00521 s.t_writes = t_writes - a.t_writes; 00522 s.p_reads = p_reads - a.p_reads; 00523 s.p_writes = p_writes - a.p_writes; 00524 s.p_ios = p_ios - a.p_ios; 00525 s.t_wait = t_wait - a.t_wait; 00526 s.t_wait_read = t_wait_read - a.t_wait_read; 00527 s.t_wait_write = t_wait_write - a.t_wait_write; 00528 s.elapsed = elapsed - a.elapsed; 00529 return s; 00530 } 00531 00532 unsigned get_reads() const 00533 { 00534 return reads; 00535 } 00536 00537 unsigned get_writes() const 00538 { 00539 return writes; 00540 } 00541 00542 int64 get_read_volume() const 00543 { 00544 return volume_read; 00545 } 00546 00547 int64 get_written_volume() const 00548 { 00549 return volume_written; 00550 } 00551 00552 unsigned get_cached_reads() const 00553 { 00554 return c_reads; 00555 } 00556 00557 unsigned get_cached_writes() const 00558 { 00559 return c_writes; 00560 } 00561 00562 int64 get_cached_read_volume() const 00563 { 00564 return c_volume_read; 00565 } 00566 00567 int64 get_cached_written_volume() const 00568 { 00569 return c_volume_written; 00570 } 00571 00572 double get_read_time() const 00573 { 00574 return t_reads; 00575 } 00576 00577 double get_write_time() const 00578 { 00579 return t_writes; 00580 } 00581 00582 double get_pread_time() const 00583 { 00584 return p_reads; 00585 } 00586 00587 double get_pwrite_time() const 00588 { 00589 return p_writes; 00590 } 00591 00592 double get_pio_time() const 00593 { 00594 return p_ios; 00595 } 00596 00597 double get_elapsed_time() const 00598 { 00599 return elapsed; 00600 } 00601 00602 double get_io_wait_time() const 00603 { 00604 return t_wait; 00605 } 00606 00607 double get_wait_read_time() const 00608 { 00609 return t_wait_read; 00610 } 00611 00612 double get_wait_write_time() const 00613 { 00614 return t_wait_write; 00615 } 00616 }; 00617 00618 std::ostream & operator << (std::ostream & o, const stats_data & s); 00619 00620 inline std::ostream & operator << (std::ostream & o, const stats & s) 00621 { 00622 o << stxxl::stats_data(s); 00623 return o; 00624 } 00625 00626 std::string format_with_SI_IEC_unit_multiplier(uint64 number, const char * unit = "", int multiplier = 1000); 00627 00628 inline std::string add_IEC_binary_multiplier(uint64 number, const char * unit = "") 00629 { 00630 return format_with_SI_IEC_unit_multiplier(number, unit, 1024); 00631 } 00632 00633 inline std::string add_SI_multiplier(uint64 number, const char * unit = "") 00634 { 00635 return format_with_SI_IEC_unit_multiplier(number, unit, 1000); 00636 } 00637 00638 //! \} 00639 00640 __STXXL_END_NAMESPACE 00641 00642 #endif // !STXXL_IOSTATS_HEADER 00643 // vim: et:ts=4:sw=4