Stxxl
1.4.0
|
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