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
|
||||
* support saving metadata in resume file, enable it by default for magnet links
|
||||
* support for receiving multi announce messages for local peer discovery
|
||||
|
|
|
@ -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
|
||||
===========
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
14
src/file.cpp
14
src/file.cpp
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue