Stxxl  1.4.0
io/iostats.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002  *  io/iostats.cpp
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 #include <string>
00016 #include <sstream>
00017 #include <iomanip>
00018 #include <stxxl/bits/io/iostats.h>
00019 #include <stxxl/bits/common/log.h>
00020 #include <stxxl/bits/verbose.h>
00021 
00022 
00023 __STXXL_BEGIN_NAMESPACE
00024 
00025 stats::stats() :
00026     reads(0),
00027     writes(0),
00028     volume_read(0),
00029     volume_written(0),
00030     c_reads(0),
00031     c_writes(0),
00032     c_volume_read(0),
00033     c_volume_written(0),
00034     t_reads(0.0),
00035     t_writes(0.0),
00036     p_reads(0.0),
00037     p_writes(0.0),
00038     p_begin_read(0.0),
00039     p_begin_write(0.0),
00040     p_ios(0.0),
00041     p_begin_io(0.0),
00042     t_waits(0.0),
00043     p_waits(0.0),
00044     p_begin_wait(0.0),
00045     t_wait_read(0.0),
00046     p_wait_read(0.0),
00047     p_begin_wait_read(0.0),
00048     t_wait_write(0.0),
00049     p_wait_write(0.0),
00050     p_begin_wait_write(0.0),
00051     acc_reads(0), acc_writes(0),
00052     acc_ios(0),
00053     acc_waits(0),
00054     acc_wait_read(0), acc_wait_write(0),
00055     last_reset(timestamp())
00056 { }
00057 
00058 #ifndef STXXL_IO_STATS_RESET_FORBIDDEN
00059 void stats::reset()
00060 {
00061     {
00062         scoped_mutex_lock ReadLock(read_mutex);
00063 
00064         //assert(acc_reads == 0);
00065         if (acc_reads)
00066             STXXL_ERRMSG("Warning: " << acc_reads <<
00067                          " read(s) not yet finished");
00068 
00069         reads = 0;
00070         volume_read = 0;
00071         c_reads = 0;
00072         c_volume_read = 0;
00073         t_reads = 0;
00074         p_reads = 0.0;
00075     }
00076     {
00077         scoped_mutex_lock WriteLock(write_mutex);
00078 
00079         //assert(acc_writes == 0);
00080         if (acc_writes)
00081             STXXL_ERRMSG("Warning: " << acc_writes <<
00082                          " write(s) not yet finished");
00083 
00084         writes = 0;
00085         volume_written = 0;
00086         c_writes = 0;
00087         c_volume_written = 0;
00088         t_writes = 0.0;
00089         p_writes = 0.0;
00090     }
00091     {
00092         scoped_mutex_lock IOLock(io_mutex);
00093 
00094         //assert(acc_ios == 0);
00095         if (acc_ios)
00096             STXXL_ERRMSG("Warning: " << acc_ios <<
00097                          " io(s) not yet finished");
00098 
00099         p_ios = 0.0;
00100     }
00101     {
00102         scoped_mutex_lock WaitLock(wait_mutex);
00103 
00104         //assert(acc_waits == 0);
00105         if (acc_waits)
00106             STXXL_ERRMSG("Warning: " << acc_waits <<
00107                          " wait(s) not yet finished");
00108 
00109         t_waits = 0.0;
00110         p_waits = 0.0;
00111         t_wait_read = 0.0;
00112         p_wait_read = 0.0;
00113         t_wait_write = 0.0;
00114         p_wait_write = 0.0;
00115     }
00116 
00117     last_reset = timestamp();
00118 }
00119 #endif
00120 
00121 #if STXXL_IO_STATS
00122 void stats::write_started(unsigned_type size_, double now)
00123 {
00124     if (now == 0.0)
00125         now = timestamp();
00126     {
00127         scoped_mutex_lock WriteLock(write_mutex);
00128 
00129         ++writes;
00130         volume_written += size_;
00131         double diff = now - p_begin_write;
00132         t_writes += double(acc_writes) * diff;
00133         p_begin_write = now;
00134         p_writes += (acc_writes++) ? diff : 0.0;
00135     }
00136     {
00137         scoped_mutex_lock IOLock(io_mutex);
00138 
00139         double diff = now - p_begin_io;
00140         p_ios += (acc_ios++) ? diff : 0.0;
00141         p_begin_io = now;
00142     }
00143 }
00144 
00145 void stats::write_canceled(unsigned_type size_)
00146 {
00147     {
00148         scoped_mutex_lock WriteLock(write_mutex);
00149 
00150         --writes;
00151         volume_written -= size_;
00152     }
00153     write_finished();
00154 }
00155 
00156 void stats::write_finished()
00157 {
00158     double now = timestamp();
00159     {
00160         scoped_mutex_lock WriteLock(write_mutex);
00161 
00162         double diff = now - p_begin_write;
00163         t_writes += double(acc_writes) * diff;
00164         p_begin_write = now;
00165         p_writes += (acc_writes--) ? diff : 0.0;
00166     }
00167     {
00168         scoped_mutex_lock IOLock(io_mutex);
00169 
00170         double diff = now - p_begin_io;
00171         p_ios += (acc_ios--) ? diff : 0.0;
00172         p_begin_io = now;
00173     }
00174 }
00175 
00176 void stats::write_cached(unsigned_type size_)
00177 {
00178     scoped_mutex_lock WriteLock(write_mutex);
00179 
00180     ++c_writes;
00181     c_volume_written += size_;
00182 }
00183 
00184 void stats::read_started(unsigned_type size_, double now)
00185 {
00186     if (now == 0.0)
00187         now = timestamp();
00188     {
00189         scoped_mutex_lock ReadLock(read_mutex);
00190 
00191         ++reads;
00192         volume_read += size_;
00193         double diff = now - p_begin_read;
00194         t_reads += double(acc_reads) * diff;
00195         p_begin_read = now;
00196         p_reads += (acc_reads++) ? diff : 0.0;
00197     }
00198     {
00199         scoped_mutex_lock IOLock(io_mutex);
00200 
00201         double diff = now - p_begin_io;
00202         p_ios += (acc_ios++) ? diff : 0.0;
00203         p_begin_io = now;
00204     }
00205 }
00206 
00207 void stats::read_canceled(unsigned_type size_)
00208 {
00209     {
00210         scoped_mutex_lock ReadLock(read_mutex);
00211 
00212         --reads;
00213         volume_read -= size_;
00214     }
00215     read_finished();
00216 }
00217 
00218 void stats::read_finished()
00219 {
00220     double now = timestamp();
00221     {
00222         scoped_mutex_lock ReadLock(read_mutex);
00223 
00224         double diff = now - p_begin_read;
00225         t_reads += double(acc_reads) * diff;
00226         p_begin_read = now;
00227         p_reads += (acc_reads--) ? diff : 0.0;
00228     }
00229     {
00230         scoped_mutex_lock IOLock(io_mutex);
00231 
00232         double diff = now - p_begin_io;
00233         p_ios += (acc_ios--) ? diff : 0.0;
00234         p_begin_io = now;
00235     }
00236 }
00237 
00238 void stats::read_cached(unsigned_type size_)
00239 {
00240     scoped_mutex_lock ReadLock(read_mutex);
00241 
00242     ++c_reads;
00243     c_volume_read += size_;
00244 }
00245 #endif
00246 
00247 #ifndef STXXL_DO_NOT_COUNT_WAIT_TIME
00248 void stats::wait_started(wait_op_type wait_op)
00249 {
00250     double now = timestamp();
00251     {
00252         scoped_mutex_lock WaitLock(wait_mutex);
00253 
00254         double diff = now - p_begin_wait;
00255         t_waits += double(acc_waits) * diff;
00256         p_begin_wait = now;
00257         p_waits += (acc_waits++) ? diff : 0.0;
00258 
00259         if (wait_op == WAIT_OP_READ) {
00260             diff = now - p_begin_wait_read;
00261             t_wait_read += double(acc_wait_read) * diff;
00262             p_begin_wait_read = now;
00263             p_wait_read += (acc_wait_read++) ? diff : 0.0;
00264         } else /* if (wait_op == WAIT_OP_WRITE) */ {
00265             // wait_any() is only used from write_pool and buffered_writer, so account WAIT_OP_ANY for WAIT_OP_WRITE, too
00266             diff = now - p_begin_wait_write;
00267             t_wait_write += double(acc_wait_write) * diff;
00268             p_begin_wait_write = now;
00269             p_wait_write += (acc_wait_write++) ? diff : 0.0;
00270         }
00271     }
00272 }
00273 
00274 void stats::wait_finished(wait_op_type wait_op)
00275 {
00276     double now = timestamp();
00277     {
00278         scoped_mutex_lock WaitLock(wait_mutex);
00279 
00280         double diff = now - p_begin_wait;
00281         t_waits += double(acc_waits) * diff;
00282         p_begin_wait = now;
00283         p_waits += (acc_waits--) ? diff : 0.0;
00284 
00285         if (wait_op == WAIT_OP_READ) {
00286             double diff = now - p_begin_wait_read;
00287             t_wait_read += double(acc_wait_read) * diff;
00288             p_begin_wait_read = now;
00289             p_wait_read += (acc_wait_read--) ? diff : 0.0;
00290         } else /* if (wait_op == WAIT_OP_WRITE) */ {
00291             double diff = now - p_begin_wait_write;
00292             t_wait_write += double(acc_wait_write) * diff;
00293             p_begin_wait_write = now;
00294             p_wait_write += (acc_wait_write--) ? diff : 0.0;
00295         }
00296 #ifdef STXXL_WAIT_LOG_ENABLED
00297         std::ofstream * waitlog = stxxl::logger::get_instance()->waitlog_stream();
00298         if (waitlog)
00299             *waitlog << (now - last_reset) << "\t"
00300                      << ((wait_op == WAIT_OP_READ) ? diff : 0.0) << "\t"
00301                      << ((wait_op != WAIT_OP_READ) ? diff : 0.0) << "\t"
00302                      << t_wait_read << "\t" << t_wait_write << std::endl << std::flush;
00303 #endif
00304     }
00305 }
00306 #endif
00307 
00308 void stats::_reset_io_wait_time()
00309 {
00310 #ifndef STXXL_DO_NOT_COUNT_WAIT_TIME
00311     {
00312         scoped_mutex_lock WaitLock(wait_mutex);
00313 
00314         //assert(acc_waits == 0);
00315         if (acc_waits)
00316             STXXL_ERRMSG("Warning: " << acc_waits <<
00317                          " wait(s) not yet finished");
00318 
00319         t_waits = 0.0;
00320         p_waits = 0.0;
00321     }
00322 #endif
00323 }
00324 
00325 std::string format_with_SI_IEC_unit_multiplier(uint64 number, const char * unit, int multiplier)
00326 {
00327     // may not overflow, std::numeric_limits<uint64>::max() == 16 EB
00328     static const char * endings[] = { "", "k", "M", "G", "T", "P", "E" };
00329     static const char * binary_endings[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" };
00330     std::ostringstream out;
00331     out << number << ' ';
00332     int scale = 0;
00333     double number_d = number;
00334     double multiplier_d = multiplier;
00335     while (number_d >= multiplier_d)
00336     {
00337         number_d /= multiplier_d;
00338         ++scale;
00339     }
00340     if (scale > 0)
00341         out << '(' << std::fixed << std::setprecision(3) << number_d << ' '
00342             << (multiplier == 1024 ? binary_endings[scale] : endings[scale])
00343             << (unit ? unit : "") << ") ";
00344     else if (unit && *unit)
00345         out << unit << ' ';
00346     return out.str();
00347 }
00348 
00349 std::ostream & operator << (std::ostream & o, const stats_data & s)
00350 {
00351 #define hr add_IEC_binary_multiplier
00352     o << "STXXL I/O statistics" << std::endl;
00353 #if STXXL_IO_STATS
00354     o << " total number of reads                      : " << hr(s.get_reads()) << std::endl;
00355     o << " average block size (read)                  : "
00356       << hr(s.get_reads() ? s.get_read_volume() / s.get_reads() : 0, "B") << std::endl;
00357     o << " number of bytes read from disks            : " << hr(s.get_read_volume(), "B") << std::endl;
00358     o << " time spent in serving all read requests    : " << s.get_read_time() << " s"
00359       << " @ " << (s.get_read_volume() / 1048576.0 / s.get_read_time()) << " MiB/s"
00360       << std::endl;
00361     o << " time spent in reading (parallel read time) : " << s.get_pread_time() << " s"
00362       << " @ " << (s.get_read_volume() / 1048576.0 / s.get_pread_time()) << " MiB/s"
00363       << std::endl;
00364    if (s.get_cached_reads()) {
00365     o << " total number of cached reads               : " << hr(s.get_cached_reads()) << std::endl;
00366     o << " average block size (cached read)           : " << hr(s.get_cached_read_volume() / s.get_cached_reads(), "B") << std::endl;
00367     o << " number of bytes read from cache            : " << hr(s.get_cached_read_volume(), "B") << std::endl;
00368    }
00369    if (s.get_cached_writes()) {
00370     o << " total number of cached writes              : " << hr(s.get_cached_writes()) << std::endl;
00371     o << " average block size (cached write)          : " << hr(s.get_cached_written_volume() / s.get_cached_writes(), "B") << std::endl;
00372     o << " number of bytes written to cache           : " << hr(s.get_cached_written_volume(), "B") << std::endl;
00373    }
00374     o << " total number of writes                     : " << hr(s.get_writes()) << std::endl;
00375     o << " average block size (write)                 : "
00376       << hr(s.get_writes() ? s.get_written_volume() / s.get_writes() : 0, "B") << std::endl;
00377     o << " number of bytes written to disks           : " << hr(s.get_written_volume(), "B") << std::endl;
00378     o << " time spent in serving all write requests   : " << s.get_write_time() << " s"
00379       << " @ " << (s.get_written_volume() / 1048576.0 / s.get_write_time()) << " MiB/s"
00380       << std::endl;
00381     o << " time spent in writing (parallel write time): " << s.get_pwrite_time() << " s"
00382       << " @ " << (s.get_written_volume() / 1048576.0 / s.get_pwrite_time()) << " MiB/s"
00383       << std::endl;
00384     o << " time spent in I/O (parallel I/O time)      : " << s.get_pio_time() << " s"
00385       << " @ " << ((s.get_read_volume() + s.get_written_volume()) / 1048576.0 / s.get_pio_time()) << " MiB/s"
00386       << std::endl;
00387 #else
00388     o << " n/a" << std::endl;
00389 #endif
00390 #ifndef STXXL_DO_NOT_COUNT_WAIT_TIME
00391     o << " I/O wait time                              : " << s.get_io_wait_time() << " s" << std::endl;
00392    if (s.get_wait_read_time() != 0.0)
00393     o << " I/O wait4read time                         : " << s.get_wait_read_time() << " s" << std::endl;
00394    if (s.get_wait_write_time() != 0.0)
00395     o << " I/O wait4write time                        : " << s.get_wait_write_time() << " s" << std::endl;
00396 #endif
00397     o << " Time since the last reset                  : " << s.get_elapsed_time() << " s" << std::endl;
00398     return o;
00399 #undef hr
00400 }
00401 
00402 __STXXL_END_NAMESPACE
00403 // vim: et:ts=4:sw=4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines