added support for fadvise/F_RDADVISE for improved disk read performance

This commit is contained in:
Arvid Norberg 2011-04-26 07:03:05 +00:00
parent 0f6b4b51e5
commit e389f5963d
10 changed files with 98 additions and 0 deletions

View File

@ -1,3 +1,4 @@
* added support for fadvise/F_RDADVISE for improved disk read performance
* introduced pop_alerts() which pops the entire alert queue in a single call
* support saving metadata in resume file, enable it by default for magnet links
* support for receiving multi announce messages for local peer discovery

View File

@ -4404,6 +4404,7 @@ session_settings
bool always_send_user_agent;
bool apply_ip_filter_to_trackers;
int read_job_every;
use_disk_read_ahead;
};
``version`` is automatically set to the libtorrent version you're using
@ -5268,6 +5269,10 @@ download rate is enough to saturate the disk, there's a risk the read jobs will
never be serviced. With this setting, every *x* write job, issued in a row, will
instead pick one read job off of the sorted queue, where *x* is ``read_job_every``.
``use_disk_read_ahead`` defaults to true and will attempt to optimize disk reads
by giving the operating system heads up of disk read requests as they are queued
in the disk job queue. This gives a significant performance boost for seeding.
pe_settings
===========

View File

@ -933,6 +933,7 @@ int main(int argc, char* argv[])
using namespace libtorrent;
session_settings settings;
settings.use_disk_read_ahead = false;
settings.user_agent = "client_test/" LIBTORRENT_VERSION;
settings.choking_algorithm = session_settings::auto_expand_choker;
//settings.announce_to_all_trackers = true;

View File

@ -241,6 +241,7 @@ namespace libtorrent
size_type writev(size_type file_offset, iovec_t const* bufs, int num_bufs, error_code& ec);
size_type readv(size_type file_offset, iovec_t const* bufs, int num_bufs, error_code& ec);
void hint_read(size_type file_offset, int len);
size_type get_size(error_code& ec) const;

View File

@ -268,6 +268,7 @@ namespace libtorrent
, always_send_user_agent(false)
, apply_ip_filter_to_trackers(true)
, read_job_every(10)
, use_disk_read_ahead(true)
{}
// libtorrent version. Used for forward binary compatibility
@ -1070,6 +1071,10 @@ namespace libtorrent
// write jobs have been taking priority in a row, service
// one read job
int read_job_every;
// issue posix_fadvise() or fcntl(F_RDADVISE) for disk reads
// ahead of time
bool use_disk_read_ahead;
};
#ifndef TORRENT_DISABLE_DHT

View File

@ -115,6 +115,7 @@ namespace libtorrent
virtual int readv(file::iovec_t const* bufs, int slot, int offset, int num_bufs);
virtual int writev(file::iovec_t const* bufs, int slot, int offset, int num_bufs);
virtual void hint_read(int slot, int offset, int len) {}
// negative return value indicates an error
virtual int read(char* buf, int slot, int offset, int size) = 0;
@ -201,6 +202,7 @@ namespace libtorrent
int read(char* buf, int slot, int offset, int size);
int write(char const* buf, int slot, int offset, int size);
int sparse_end(int start) const;
void hint_read(int slot, int offset, int len);
int readv(file::iovec_t const* bufs, int slot, int offset, int num_bufs);
int writev(file::iovec_t const* buf, int slot, int offset, int num_bufs);
size_type physical_offset(int slot, int offset);
@ -422,6 +424,8 @@ namespace libtorrent
int hash_for_slot(int slot, partial_hash& h, int piece_size
, int small_piece_size = 0, sha1_hash* small_hash = 0);
void hint_read_impl(int piece_index, int offset, int size);
int read_impl(
file::iovec_t* bufs
, int piece_index

View File

@ -1722,6 +1722,11 @@ namespace libtorrent
}
}
if (m_settings.use_disk_read_ahead && defer)
{
j.storage->hint_read_impl(j.piece, j.offset, j.buffer_size);
}
TORRENT_ASSERT(j.offset >= 0);
if (m_settings.allow_reordered_disk_operations && defer)
{

View File

@ -1014,6 +1014,20 @@ namespace libtorrent
#endif
void file::hint_read(size_type file_offset, int len)
{
#if defined POSIX_FADV_WILLNEED
posix_fadvise(m_fd, file_offset, len, POSIX_FADV_WILLNEED);
#elif defined F_RDADVISE
radvisory r;
r.ra_offset = file_offset;
r.ra_count = len;
fcntl(m_fd, F_RDADVISE, &r);
#else
// TODO: is there any way to pre-fetch data from a file on windows?
#endif
}
size_type file::readv(size_type file_offset, iovec_t const* bufs, int num_bufs, error_code& ec)
{
TORRENT_ASSERT((m_open_mode & rw_mask) == read_only || (m_open_mode & rw_mask) == read_write);

View File

@ -149,6 +149,7 @@ namespace libtorrent
set.cache_size = 0;
set.cache_buffer_chunk_size = 1;
set.use_read_cache = false;
set.use_disk_read_ahead = false;
set.close_redundant_connections = true;

View File

@ -1011,6 +1011,59 @@ ret:
return ret;
}
void default_storage::hint_read(int slot, int offset, int size)
{
size_type start = slot * (size_type)m_files.piece_length() + offset;
TORRENT_ASSERT(start + size <= m_files.total_size());
size_type file_offset = start;
file_storage::iterator file_iter;
// TODO: use binary search!
for (file_iter = files().begin();;)
{
if (file_offset < file_iter->size)
break;
file_offset -= file_iter->size;
++file_iter;
TORRENT_ASSERT(file_iter != files().end());
}
boost::intrusive_ptr<file> file_handle;
int bytes_left = size;
int slot_size = static_cast<int>(m_files.piece_size(slot));
if (offset + bytes_left > slot_size)
bytes_left = slot_size - offset;
TORRENT_ASSERT(bytes_left >= 0);
int file_bytes_left;
for (;bytes_left > 0; ++file_iter, bytes_left -= file_bytes_left)
{
TORRENT_ASSERT(file_iter != files().end());
file_bytes_left = bytes_left;
if (file_offset + file_bytes_left > file_iter->size)
file_bytes_left = (std::max)(static_cast<int>(file_iter->size - file_offset), 0);
if (file_bytes_left == 0) continue;
if (file_iter->pad_file) continue;
error_code ec;
file_handle = open_file(file_iter, file::read_only, ec);
// failing to hint that we want to read is not a big deal
// just swollow the error and keep going
if (!file_handle || ec) continue;
file_handle->hint_read(file_offset, file_bytes_left);
file_offset = 0;
}
}
int default_storage::readv(file::iovec_t const* bufs, int slot, int offset
, int num_bufs)
{
@ -1072,6 +1125,7 @@ ret:
size_type file_offset = start;
file_storage::iterator file_iter;
// TODO: use binary search!
for (file_iter = files().begin();;)
{
if (file_offset < file_iter->size)
@ -1698,6 +1752,13 @@ ret:
m_free_slots.push_back(slot_index);
}
void piece_manager::hint_read_impl(int piece_index, int offset, int size)
{
m_last_piece = piece_index;
int slot = slot_for(piece_index);
m_storage->hint_read(slot, offset, size);
}
int piece_manager::read_impl(
file::iovec_t* bufs
, int piece_index