added support for fadvise/F_RDADVISE for improved disk read performance
This commit is contained in:
parent
0f6b4b51e5
commit
e389f5963d
|
@ -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
|
* 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 saving metadata in resume file, enable it by default for magnet links
|
||||||
* support for receiving multi announce messages for local peer discovery
|
* support for receiving multi announce messages for local peer discovery
|
||||||
|
|
|
@ -4404,6 +4404,7 @@ session_settings
|
||||||
bool always_send_user_agent;
|
bool always_send_user_agent;
|
||||||
bool apply_ip_filter_to_trackers;
|
bool apply_ip_filter_to_trackers;
|
||||||
int read_job_every;
|
int read_job_every;
|
||||||
|
use_disk_read_ahead;
|
||||||
};
|
};
|
||||||
|
|
||||||
``version`` is automatically set to the libtorrent version you're using
|
``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
|
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``.
|
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
|
pe_settings
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
|
|
@ -933,6 +933,7 @@ int main(int argc, char* argv[])
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
session_settings settings;
|
session_settings settings;
|
||||||
|
|
||||||
|
settings.use_disk_read_ahead = false;
|
||||||
settings.user_agent = "client_test/" LIBTORRENT_VERSION;
|
settings.user_agent = "client_test/" LIBTORRENT_VERSION;
|
||||||
settings.choking_algorithm = session_settings::auto_expand_choker;
|
settings.choking_algorithm = session_settings::auto_expand_choker;
|
||||||
//settings.announce_to_all_trackers = true;
|
//settings.announce_to_all_trackers = true;
|
||||||
|
|
|
@ -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 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);
|
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;
|
size_type get_size(error_code& ec) const;
|
||||||
|
|
||||||
|
|
|
@ -268,6 +268,7 @@ namespace libtorrent
|
||||||
, always_send_user_agent(false)
|
, always_send_user_agent(false)
|
||||||
, apply_ip_filter_to_trackers(true)
|
, apply_ip_filter_to_trackers(true)
|
||||||
, read_job_every(10)
|
, read_job_every(10)
|
||||||
|
, use_disk_read_ahead(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// libtorrent version. Used for forward binary compatibility
|
// libtorrent version. Used for forward binary compatibility
|
||||||
|
@ -1070,6 +1071,10 @@ namespace libtorrent
|
||||||
// write jobs have been taking priority in a row, service
|
// write jobs have been taking priority in a row, service
|
||||||
// one read job
|
// one read job
|
||||||
int read_job_every;
|
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
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
|
|
|
@ -115,6 +115,7 @@ namespace libtorrent
|
||||||
virtual int readv(file::iovec_t const* bufs, int slot, int offset, int num_bufs);
|
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 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
|
// negative return value indicates an error
|
||||||
virtual int read(char* buf, int slot, int offset, int size) = 0;
|
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 read(char* buf, int slot, int offset, int size);
|
||||||
int write(char const* buf, int slot, int offset, int size);
|
int write(char const* buf, int slot, int offset, int size);
|
||||||
int sparse_end(int start) const;
|
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 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);
|
int writev(file::iovec_t const* buf, int slot, int offset, int num_bufs);
|
||||||
size_type physical_offset(int slot, int offset);
|
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 hash_for_slot(int slot, partial_hash& h, int piece_size
|
||||||
, int small_piece_size = 0, sha1_hash* small_hash = 0);
|
, int small_piece_size = 0, sha1_hash* small_hash = 0);
|
||||||
|
|
||||||
|
void hint_read_impl(int piece_index, int offset, int size);
|
||||||
|
|
||||||
int read_impl(
|
int read_impl(
|
||||||
file::iovec_t* bufs
|
file::iovec_t* bufs
|
||||||
, int piece_index
|
, int piece_index
|
||||||
|
|
|
@ -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);
|
TORRENT_ASSERT(j.offset >= 0);
|
||||||
if (m_settings.allow_reordered_disk_operations && defer)
|
if (m_settings.allow_reordered_disk_operations && defer)
|
||||||
{
|
{
|
||||||
|
|
14
src/file.cpp
14
src/file.cpp
|
@ -1014,6 +1014,20 @@ namespace libtorrent
|
||||||
|
|
||||||
#endif
|
#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)
|
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);
|
TORRENT_ASSERT((m_open_mode & rw_mask) == read_only || (m_open_mode & rw_mask) == read_write);
|
||||||
|
|
|
@ -149,6 +149,7 @@ namespace libtorrent
|
||||||
set.cache_size = 0;
|
set.cache_size = 0;
|
||||||
set.cache_buffer_chunk_size = 1;
|
set.cache_buffer_chunk_size = 1;
|
||||||
set.use_read_cache = false;
|
set.use_read_cache = false;
|
||||||
|
set.use_disk_read_ahead = false;
|
||||||
|
|
||||||
set.close_redundant_connections = true;
|
set.close_redundant_connections = true;
|
||||||
|
|
||||||
|
|
|
@ -1011,6 +1011,59 @@ ret:
|
||||||
return 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 default_storage::readv(file::iovec_t const* bufs, int slot, int offset
|
||||||
, int num_bufs)
|
, int num_bufs)
|
||||||
{
|
{
|
||||||
|
@ -1072,6 +1125,7 @@ ret:
|
||||||
size_type file_offset = start;
|
size_type file_offset = start;
|
||||||
file_storage::iterator file_iter;
|
file_storage::iterator file_iter;
|
||||||
|
|
||||||
|
// TODO: use binary search!
|
||||||
for (file_iter = files().begin();;)
|
for (file_iter = files().begin();;)
|
||||||
{
|
{
|
||||||
if (file_offset < file_iter->size)
|
if (file_offset < file_iter->size)
|
||||||
|
@ -1698,6 +1752,13 @@ ret:
|
||||||
m_free_slots.push_back(slot_index);
|
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(
|
int piece_manager::read_impl(
|
||||||
file::iovec_t* bufs
|
file::iovec_t* bufs
|
||||||
, int piece_index
|
, int piece_index
|
||||||
|
|
Loading…
Reference in New Issue