added more detailed instrumentation of the disk I/O thread

This commit is contained in:
Arvid Norberg 2010-03-03 07:09:04 +00:00
parent fdb68ab784
commit a942890e8d
5 changed files with 112 additions and 1 deletions

View File

@ -16,6 +16,7 @@
* support for BitTyrant choker algorithm
* support for automatically start torrents when they receive an
incoming connection
* added more detailed instrumentation of the disk I/O thread
0.15 release

View File

@ -820,6 +820,9 @@ Returns status of the disk cache for this session.
int cache_size;
int read_cache_size;
int total_used_buffers;
int average_queue_time;
int average_read_time;
int job_queue_length;
};
``blocks_written`` is the total number of 16 KiB blocks written to disk
@ -849,6 +852,14 @@ This includes both read and write cache.
This includes the read/write disk cache as well as send and receive buffers
used in peer connections.
``average_queue_time`` is the number of microseconds an average disk I/O job
has to wait in the job queue before it get processed.
``average_read_time`` is the number of microseconds a read job takes to
wait in the queue and complete, in microseconds.
``job_queue_length`` is the number of jobs in the job queue.
get_cache_info()
----------------

View File

@ -40,6 +40,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/storage.hpp"
#include "libtorrent/allocator.hpp"
#include "libtorrent/io_service.hpp"
#include "libtorrent/sliding_average.hpp"
#include <boost/function/function0.hpp>
#include <boost/function/function2.hpp>
@ -140,6 +141,10 @@ namespace libtorrent
// this is called when operation completes
boost::function<void(int, disk_io_job const&)> callback;
// the time when this job was issued. This is used to
// keep track of disk I/O congestion
ptime start_time;
};
// returns true if the fundamental operation
@ -189,6 +194,11 @@ namespace libtorrent
// the total number of blocks that are currently in use
// this includes send and receive buffers
mutable int total_used_buffers;
// times in microseconds
int average_queue_time;
int average_read_time;
int job_queue_length;
};
struct TORRENT_EXPORT disk_buffer_pool : boost::noncopyable
@ -408,6 +418,12 @@ namespace libtorrent
// exceed m_cache_size
cache_status m_cache_stats;
// keeps average queue time for disk jobs (in microseconds)
sliding_average m_queue_time;
// average read time for cache misses (in microseconds)
sliding_average m_read_time;
#ifdef TORRENT_DISK_STATS
std::ofstream m_log;
#endif

View File

@ -0,0 +1,70 @@
/*
Copyright (c) 2010, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
namespace libtorrent
{
// a sliding average accumulator. Add samples to it and it
// keeps track of a sliding mean value and an average deviation
// from that average.
struct sliding_average
{
sliding_average(): m_mean(-1), m_average_deviation(-1) {}
void add_sample(int s)
{
if (m_mean == -1)
{
m_mean = s;
return;
}
int deviation = abs(m_mean - s);
m_mean = m_mean - m_mean / 16 + s / 16;
if (m_average_deviation == -1)
{
m_average_deviation = deviation;
return;
}
m_average_deviation = m_average_deviation - m_average_deviation / 16 + deviation / 16;
}
int mean() const { return m_mean != -1 ? m_mean : 0; }
int avg_deviation() const { return m_average_deviation != -1 ? m_average_deviation : 0; }
private:
int m_mean;
int m_average_deviation;
};
}

View File

@ -362,7 +362,14 @@ namespace libtorrent
mutex::scoped_lock l(m_piece_mutex);
m_cache_stats.total_used_buffers = in_use();
m_cache_stats.queued_bytes = m_queue_buffer_size;
return m_cache_stats;
cache_status ret = m_cache_stats;
ret.average_queue_time = m_queue_time.mean();
ret.average_read_time = m_read_time.mean();
ret.job_queue_length = m_jobs.size();
return ret;
}
// aborts read operations
@ -1315,6 +1322,7 @@ namespace libtorrent
{
m_jobs.push_back(j);
m_jobs.back().callback.swap(const_cast<boost::function<void(int, disk_io_job const&)>&>(f));
m_jobs.back().start_time = time_now_hires();
if (j.action == disk_io_job::write)
m_queue_buffer_size += j.buffer_size;
@ -1591,6 +1599,9 @@ namespace libtorrent
if (j.storage && j.storage->get_storage_impl()->m_settings == 0)
j.storage->get_storage_impl()->m_settings = &m_settings;
ptime now = time_now_hires();
m_queue_time.add_sample(total_microseconds(now - j.start_time));
switch (j.action)
{
case disk_io_job::update_settings:
@ -2216,6 +2227,8 @@ namespace libtorrent
&& j.buffer != 0)
rename_buffer(j.buffer, "posted send buffer");
#endif
ptime now = time_now_hires();
m_read_time.add_sample(total_microseconds(now - j.start_time));
post_callback(j.callback, j, ret);
#ifndef BOOST_NO_EXCEPTIONS
} catch (std::exception&)