Stxxl  1.4.0
include/stxxl/bits/io/iostats.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines