added an option to generate a disk io log file

This commit is contained in:
Arvid Norberg 2007-09-17 08:15:54 +00:00
parent 4d4204a3a7
commit b5a2373bff
4 changed files with 124 additions and 1 deletions

View File

@ -139,6 +139,9 @@ rule building ( properties * )
return $(result) ; return $(result) ;
} }
feature disk-stats : off on : composite propagated symmetric link-incompatible ;
feature.compose <disk-stats>on : <define>TORRENT_DISK_STATS ;
feature logging : none default verbose : composite propagated symmetric link-incompatible ; feature logging : none default verbose : composite propagated symmetric link-incompatible ;
feature.compose <logging>default : <define>TORRENT_LOGGING ; feature.compose <logging>default : <define>TORRENT_LOGGING ;
feature.compose <logging>verbose : <define>TORRENT_VERBOSE_LOGGING ; feature.compose <logging>verbose : <define>TORRENT_VERBOSE_LOGGING ;

View File

@ -30,6 +30,10 @@ POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifdef TORRENT_DISK_STATS
#include <fstream>
#endif
#include "libtorrent/storage.hpp" #include "libtorrent/storage.hpp"
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
@ -122,6 +126,10 @@ namespace libtorrent
int m_block_size; int m_block_size;
#endif #endif
#ifdef TORRENT_DISK_STATS
std::ofstream m_log;
#endif
// thread for performing blocking disk io operations // thread for performing blocking disk io operations
boost::thread m_disk_io_thread; boost::thread m_disk_io_thread;
}; };

68
parse_disk_log.py Normal file
View File

@ -0,0 +1,68 @@
import os, sys, time
lines = open(sys.argv[1], 'rb').readlines()
time_limit = -1
if len(sys.argv) > 2:
time_limit = long(sys.argv[2])
keys = ['write', 'read', 'hash', 'move', 'release', 'idle']
# logfile format:
# <time(ms)> <state>
# example:
# 34523 idle
# 34722 write
quantization = 5000
out = open('disk_io.dat', 'wb')
state = 'idle'
time = 0
i = 0
state_timer = {}
for k in keys: state_timer[k] = 0
for l in lines:
l = l[:-1].split(' ')
if len(l) < 2:
print l
continue
try:
new_time = long(l[0])
while new_time > i + quantization:
i += quantization
state_timer[state] += i - time
time = i
for k in keys: print >>out, state_timer[k],
print >>out
for k in keys: state_timer[k] = 0
state_timer[state] += new_time - time
time = new_time
state = l[1]
except:
print l
out.close()
out = open('disk_io.gnuplot', 'wb')
print >>out, "set term png size 1200,700"
print >>out, 'set output "disk_io.png"'
print >>out, 'set xrange [0:*]'
print >>out, 'set ylabel "time (ms)"'
print >>out, "set style data lines"
print >>out, 'set title "disk io utilization per %s second(s)"' % (quantization / 1000)
print >>out, "set key box"
print >>out, "set style data histogram"
print >>out, "set style histogram rowstacked"
print >>out, "set style fill solid"
print >>out, 'plot',
i = 0
for k in keys:
if k != 'idle':
print >>out, ' "disk_io.dat" using %d title "%s",' % (i + 1, keys[i]),
i = i + 1
print >>out, 'x=0'
out.close()
os.system('gnuplot disk_io.gnuplot');

View File

@ -34,6 +34,24 @@ POSSIBILITY OF SUCH DAMAGE.
#include <deque> #include <deque>
#include "libtorrent/disk_io_thread.hpp" #include "libtorrent/disk_io_thread.hpp"
#ifdef TORRENT_DISK_STATS
#include "libtorrent/time.hpp"
#include <boost/lexical_cast.hpp>
namespace
{
std::string log_time()
{
using namespace libtorrent;
static ptime start = time_now();
return boost::lexical_cast<std::string>(
total_milliseconds(time_now() - start));
}
}
#endif
namespace libtorrent namespace libtorrent
{ {
@ -45,7 +63,12 @@ namespace libtorrent
, m_block_size(block_size) , m_block_size(block_size)
#endif #endif
, m_disk_io_thread(boost::ref(*this)) , m_disk_io_thread(boost::ref(*this))
{} {
#ifdef TORRENT_DISK_STATS
m_log.open("disk_io_thread.log", std::ios::trunc);
#endif
}
disk_io_thread::~disk_io_thread() disk_io_thread::~disk_io_thread()
{ {
@ -172,6 +195,9 @@ namespace libtorrent
{ {
for (;;) for (;;)
{ {
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " idle" << std::endl;
#endif
boost::mutex::scoped_lock l(m_mutex); boost::mutex::scoped_lock l(m_mutex);
while (m_jobs.empty() && !m_abort) while (m_jobs.empty() && !m_abort)
m_signal.wait(l); m_signal.wait(l);
@ -189,10 +215,16 @@ namespace libtorrent
bool free_buffer = true; bool free_buffer = true;
try try
{ {
#ifdef TORRENT_DISK_STATS
ptime start = time_now();
#endif
// std::cerr << "DISK THREAD: executing job: " << j.action << std::endl; // std::cerr << "DISK THREAD: executing job: " << j.action << std::endl;
switch (j.action) switch (j.action)
{ {
case disk_io_job::read: case disk_io_job::read:
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " read " << j.buffer_size << std::endl;
#endif
if (j.buffer == 0) if (j.buffer == 0)
{ {
l.lock(); l.lock();
@ -217,6 +249,9 @@ namespace libtorrent
// usleep(300); // usleep(300);
break; break;
case disk_io_job::write: case disk_io_job::write:
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " write " << j.buffer_size << std::endl;
#endif
assert(j.buffer); assert(j.buffer);
assert(j.buffer_size <= m_block_size); assert(j.buffer_size <= m_block_size);
j.storage->write_impl(j.buffer, j.piece, j.offset j.storage->write_impl(j.buffer, j.piece, j.offset
@ -227,16 +262,25 @@ namespace libtorrent
break; break;
case disk_io_job::hash: case disk_io_job::hash:
{ {
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " hash" << std::endl;
#endif
sha1_hash h = j.storage->hash_for_piece_impl(j.piece); sha1_hash h = j.storage->hash_for_piece_impl(j.piece);
j.str.resize(20); j.str.resize(20);
std::memcpy(&j.str[0], &h[0], 20); std::memcpy(&j.str[0], &h[0], 20);
} }
break; break;
case disk_io_job::move_storage: case disk_io_job::move_storage:
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " move" << std::endl;
#endif
ret = j.storage->move_storage_impl(j.str) ? 1 : 0; ret = j.storage->move_storage_impl(j.str) ? 1 : 0;
j.str = j.storage->save_path().string(); j.str = j.storage->save_path().string();
break; break;
case disk_io_job::release_files: case disk_io_job::release_files:
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " release" << std::endl;
#endif
j.storage->release_files_impl(); j.storage->release_files_impl();
break; break;
} }