Browse Source

Allow to use POSIX-compliant disk IO type

This patch allows user to switch disk IO type between memory mapped files based type (default in libtorrent 2, and seems causing memory issues) and POSIX-compliant type which is more conservative on memory usage.

Co-authored-by: Chocobo1 <Chocobo1@users.noreply.github.com>
Co-authored-by: Vladimir Golovnev (Glassez) <glassez@yandex.ru>

PR #16895.
adaptive-webui-19844
Coda 3 years ago committed by GitHub
parent
commit
e698c09298
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      src/base/bittorrent/customstorage.cpp
  2. 4
      src/base/bittorrent/customstorage.h
  3. 25
      src/base/bittorrent/session.cpp
  4. 11
      src/base/bittorrent/session.h
  5. 15
      src/gui/advancedsettings.cpp
  6. 1
      src/gui/advancedsettings.h
  7. 5
      src/webui/api/appcontroller.cpp
  8. 14
      src/webui/www/private/views/preferences.html

14
src/base/bittorrent/customstorage.cpp

@ -34,6 +34,8 @@
#include "common.h" #include "common.h"
#ifdef QBT_USES_LIBTORRENT2 #ifdef QBT_USES_LIBTORRENT2
#include <libtorrent/mmap_disk_io.hpp>
#include <libtorrent/posix_disk_io.hpp>
#include <libtorrent/session.hpp> #include <libtorrent/session.hpp>
std::unique_ptr<lt::disk_interface> customDiskIOConstructor( std::unique_ptr<lt::disk_interface> customDiskIOConstructor(
@ -42,6 +44,18 @@ std::unique_ptr<lt::disk_interface> customDiskIOConstructor(
return std::make_unique<CustomDiskIOThread>(lt::default_disk_io_constructor(ioContext, settings, counters)); return std::make_unique<CustomDiskIOThread>(lt::default_disk_io_constructor(ioContext, settings, counters));
} }
std::unique_ptr<lt::disk_interface> customPosixDiskIOConstructor(
lt::io_context &ioContext, const lt::settings_interface &settings, lt::counters &counters)
{
return std::make_unique<CustomDiskIOThread>(lt::posix_disk_io_constructor(ioContext, settings, counters));
}
std::unique_ptr<lt::disk_interface> customMMapDiskIOConstructor(
lt::io_context &ioContext, const lt::settings_interface &settings, lt::counters &counters)
{
return std::make_unique<CustomDiskIOThread>(lt::mmap_disk_io_constructor(ioContext, settings, counters));
}
CustomDiskIOThread::CustomDiskIOThread(std::unique_ptr<libtorrent::disk_interface> nativeDiskIOThread) CustomDiskIOThread::CustomDiskIOThread(std::unique_ptr<libtorrent::disk_interface> nativeDiskIOThread)
: m_nativeDiskIO {std::move(nativeDiskIOThread)} : m_nativeDiskIO {std::move(nativeDiskIOThread)}
{ {

4
src/base/bittorrent/customstorage.h

@ -50,6 +50,10 @@
#ifdef QBT_USES_LIBTORRENT2 #ifdef QBT_USES_LIBTORRENT2
std::unique_ptr<lt::disk_interface> customDiskIOConstructor( std::unique_ptr<lt::disk_interface> customDiskIOConstructor(
lt::io_context &ioContext, lt::settings_interface const &settings, lt::counters &counters); lt::io_context &ioContext, lt::settings_interface const &settings, lt::counters &counters);
std::unique_ptr<lt::disk_interface> customPosixDiskIOConstructor(
lt::io_context &ioContext, lt::settings_interface const &settings, lt::counters &counters);
std::unique_ptr<lt::disk_interface> customMMapDiskIOConstructor(
lt::io_context &ioContext, lt::settings_interface const &settings, lt::counters &counters);
class CustomDiskIOThread final : public lt::disk_interface class CustomDiskIOThread final : public lt::disk_interface
{ {

25
src/base/bittorrent/session.cpp

@ -381,6 +381,7 @@ Session::Session(QObject *parent)
, m_diskCacheSize(BITTORRENT_SESSION_KEY(u"DiskCacheSize"_qs), -1) , m_diskCacheSize(BITTORRENT_SESSION_KEY(u"DiskCacheSize"_qs), -1)
, m_diskCacheTTL(BITTORRENT_SESSION_KEY(u"DiskCacheTTL"_qs), 60) , m_diskCacheTTL(BITTORRENT_SESSION_KEY(u"DiskCacheTTL"_qs), 60)
, m_diskQueueSize(BITTORRENT_SESSION_KEY(u"DiskQueueSize"_qs), (1024 * 1024)) , m_diskQueueSize(BITTORRENT_SESSION_KEY(u"DiskQueueSize"_qs), (1024 * 1024))
, m_diskIOType(BITTORRENT_SESSION_KEY(u"DiskIOType"_qs), DiskIOType::Default)
, m_useOSCache(BITTORRENT_SESSION_KEY(u"UseOSCache"_qs), true) , m_useOSCache(BITTORRENT_SESSION_KEY(u"UseOSCache"_qs), true)
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
, m_coalesceReadWriteEnabled(BITTORRENT_SESSION_KEY(u"CoalesceReadWrite"_qs), true) , m_coalesceReadWriteEnabled(BITTORRENT_SESSION_KEY(u"CoalesceReadWrite"_qs), true)
@ -1149,7 +1150,18 @@ void Session::initializeNativeSession()
loadLTSettings(pack); loadLTSettings(pack);
lt::session_params sessionParams {pack, {}}; lt::session_params sessionParams {pack, {}};
#ifdef QBT_USES_LIBTORRENT2 #ifdef QBT_USES_LIBTORRENT2
switch (diskIOType())
{
case DiskIOType::Posix:
sessionParams.disk_io_constructor = customPosixDiskIOConstructor;
break;
case DiskIOType::MMap:
sessionParams.disk_io_constructor = customMMapDiskIOConstructor;
break;
default:
sessionParams.disk_io_constructor = customDiskIOConstructor; sessionParams.disk_io_constructor = customDiskIOConstructor;
break;
}
#endif #endif
m_nativeSession = new lt::session {sessionParams}; m_nativeSession = new lt::session {sessionParams};
@ -3363,6 +3375,19 @@ void Session::setPeerTurnoverInterval(const int val)
configureDeferred(); configureDeferred();
} }
DiskIOType Session::diskIOType() const
{
return m_diskIOType;
}
void Session::setDiskIOType(const DiskIOType type)
{
if (type != m_diskIOType)
{
m_diskIOType = type;
}
}
int Session::requestQueueSize() const int Session::requestQueueSize() const
{ {
return m_requestQueueSize; return m_requestQueueSize;

11
src/base/bittorrent/session.h

@ -122,6 +122,14 @@ namespace BitTorrent
}; };
Q_ENUM_NS(ChokingAlgorithm) Q_ENUM_NS(ChokingAlgorithm)
enum class DiskIOType : int
{
Default = 0,
MMap = 1,
Posix = 2
};
Q_ENUM_NS(DiskIOType)
enum class MixedModeAlgorithm : int enum class MixedModeAlgorithm : int
{ {
TCP = 0, TCP = 0,
@ -368,6 +376,8 @@ namespace BitTorrent
void setDiskCacheTTL(int ttl); void setDiskCacheTTL(int ttl);
qint64 diskQueueSize() const; qint64 diskQueueSize() const;
void setDiskQueueSize(qint64 size); void setDiskQueueSize(qint64 size);
DiskIOType diskIOType() const;
void setDiskIOType(DiskIOType type);
bool useOSCache() const; bool useOSCache() const;
void setUseOSCache(bool use); void setUseOSCache(bool use);
bool isCoalesceReadWriteEnabled() const; bool isCoalesceReadWriteEnabled() const;
@ -689,6 +699,7 @@ namespace BitTorrent
CachedSettingValue<int> m_diskCacheSize; CachedSettingValue<int> m_diskCacheSize;
CachedSettingValue<int> m_diskCacheTTL; CachedSettingValue<int> m_diskCacheTTL;
CachedSettingValue<qint64> m_diskQueueSize; CachedSettingValue<qint64> m_diskQueueSize;
CachedSettingValue<DiskIOType> m_diskIOType;
CachedSettingValue<bool> m_useOSCache; CachedSettingValue<bool> m_useOSCache;
CachedSettingValue<bool> m_coalesceReadWriteEnabled; CachedSettingValue<bool> m_coalesceReadWriteEnabled;
CachedSettingValue<bool> m_usePieceExtentAffinity; CachedSettingValue<bool> m_usePieceExtentAffinity;

15
src/gui/advancedsettings.cpp

@ -108,6 +108,9 @@ namespace
DISK_CACHE_TTL, DISK_CACHE_TTL,
#endif #endif
DISK_QUEUE_SIZE, DISK_QUEUE_SIZE,
#ifdef QBT_USES_LIBTORRENT2
DISK_IO_TYPE,
#endif
OS_CACHE, OS_CACHE,
#ifndef QBT_USES_LIBTORRENT2 #ifndef QBT_USES_LIBTORRENT2
COALESCE_RW, COALESCE_RW,
@ -219,6 +222,9 @@ void AdvancedSettings::saveAdvancedSettings()
#endif #endif
// Disk queue size // Disk queue size
session->setDiskQueueSize(m_spinBoxDiskQueueSize.value() * 1024); session->setDiskQueueSize(m_spinBoxDiskQueueSize.value() * 1024);
#ifdef QBT_USES_LIBTORRENT2
session->setDiskIOType(m_comboBoxDiskIOType.currentData().value<BitTorrent::DiskIOType>());
#endif
// Enable OS cache // Enable OS cache
session->setUseOSCache(m_checkBoxOsCache.isChecked()); session->setUseOSCache(m_checkBoxOsCache.isChecked());
#ifndef QBT_USES_LIBTORRENT2 #ifndef QBT_USES_LIBTORRENT2
@ -521,6 +527,15 @@ void AdvancedSettings::loadAdvancedSettings()
m_spinBoxDiskQueueSize.setSuffix(tr(" KiB")); m_spinBoxDiskQueueSize.setSuffix(tr(" KiB"));
addRow(DISK_QUEUE_SIZE, (tr("Disk queue size") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#max_queued_disk_bytes", u"(?)")) addRow(DISK_QUEUE_SIZE, (tr("Disk queue size") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#max_queued_disk_bytes", u"(?)"))
, &m_spinBoxDiskQueueSize); , &m_spinBoxDiskQueueSize);
#ifdef QBT_USES_LIBTORRENT2
// Disk IO type
m_comboBoxDiskIOType.addItem(tr("Default"), QVariant::fromValue(BitTorrent::DiskIOType::Default));
m_comboBoxDiskIOType.addItem(tr("Memory mapped files"), QVariant::fromValue(BitTorrent::DiskIOType::MMap));
m_comboBoxDiskIOType.addItem(tr("POSIX-compliant"), QVariant::fromValue(BitTorrent::DiskIOType::Posix));
m_comboBoxDiskIOType.setCurrentIndex(m_comboBoxDiskIOType.findData(QVariant::fromValue(session->diskIOType())));
addRow(DISK_IO_TYPE, tr("Disk IO type (requires restart)") + u' ' + makeLink(u"https://www.libtorrent.org/single-page-ref.html#default-disk-io-constructor", u"(?)")
, &m_comboBoxDiskIOType);
#endif
// Enable OS cache // Enable OS cache
m_checkBoxOsCache.setChecked(session->useOSCache()); m_checkBoxOsCache.setChecked(session->useOSCache());
addRow(OS_CACHE, (tr("Enable OS cache") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#disk_io_write_mode", u"(?)")) addRow(OS_CACHE, (tr("Enable OS cache") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#disk_io_write_mode", u"(?)"))

1
src/gui/advancedsettings.h

@ -76,6 +76,7 @@ private:
QSpinBox m_spinBoxCache, m_spinBoxCacheTTL; QSpinBox m_spinBoxCache, m_spinBoxCacheTTL;
QCheckBox m_checkBoxCoalesceRW; QCheckBox m_checkBoxCoalesceRW;
#else #else
QComboBox m_comboBoxDiskIOType;
QSpinBox m_spinBoxHashingThreads; QSpinBox m_spinBoxHashingThreads;
#endif #endif

5
src/webui/api/appcontroller.cpp

@ -315,6 +315,8 @@ void AppController::preferencesAction()
data[u"disk_cache_ttl"_qs] = session->diskCacheTTL(); data[u"disk_cache_ttl"_qs] = session->diskCacheTTL();
// Disk queue size // Disk queue size
data[u"disk_queue_size"_qs] = session->diskQueueSize(); data[u"disk_queue_size"_qs] = session->diskQueueSize();
// Disk IO Type
data[u"disk_io_type"_qs] = static_cast<int>(session->diskIOType());
// Enable OS cache // Enable OS cache
data[u"enable_os_cache"_qs] = session->useOSCache(); data[u"enable_os_cache"_qs] = session->useOSCache();
// Coalesce reads & writes // Coalesce reads & writes
@ -799,6 +801,9 @@ void AppController::setPreferencesAction()
// Disk queue size // Disk queue size
if (hasKey(u"disk_queue_size"_qs)) if (hasKey(u"disk_queue_size"_qs))
session->setDiskQueueSize(it.value().toLongLong()); session->setDiskQueueSize(it.value().toLongLong());
// Disk IO Type
if (hasKey(u"disk_io_type"_qs))
session->setDiskIOType(static_cast<BitTorrent::DiskIOType>(it.value().toInt()));
// Enable OS cache // Enable OS cache
if (hasKey(u"enable_os_cache"_qs)) if (hasKey(u"enable_os_cache"_qs))
session->setUseOSCache(it.value().toBool()); session->setUseOSCache(it.value().toBool());

14
src/webui/www/private/views/preferences.html

@ -1038,6 +1038,18 @@
<input type="text" id="diskQueueSize" style="width: 15em;">&nbsp;&nbsp;QBT_TR(KiB)QBT_TR[CONTEXT=OptionsDialog] <input type="text" id="diskQueueSize" style="width: 15em;">&nbsp;&nbsp;QBT_TR(KiB)QBT_TR[CONTEXT=OptionsDialog]
</td> </td>
</tr> </tr>
<tr>
<td>
<label for="diskIOType">QBT_TR(Disk IO type (libtorrent >= 2.0; requires restart):)QBT_TR[CONTEXT=OptionsDialog]&nbsp;<a href="https://www.libtorrent.org/single-page-ref.html#default-disk-io-constructor" target="_blank">(?)</a></label>
</td>
<td>
<select id="diskIOType" style="width: 15em;">
<option value="0">QBT_TR(Default)QBT_TR[CONTEXT=OptionsDialog]</option>
<option value="1">QBT_TR(Memory mapped files)QBT_TR[CONTEXT=OptionsDialog]</option>
<option value="2">QBT_TR(POSIX-compliant)QBT_TR[CONTEXT=OptionsDialog]</option>
</select>
</td>
</tr>
<tr> <tr>
<td> <td>
<label for="enableOSCache">QBT_TR(Enable OS cache:)QBT_TR[CONTEXT=OptionsDialog]&nbsp;<a href="https://www.libtorrent.org/reference-Settings.html#disk_io_write_mode" target="_blank">(?)</a></label> <label for="enableOSCache">QBT_TR(Enable OS cache:)QBT_TR[CONTEXT=OptionsDialog]&nbsp;<a href="https://www.libtorrent.org/reference-Settings.html#disk_io_write_mode" target="_blank">(?)</a></label>
@ -1970,6 +1982,7 @@
$('diskCache').setProperty('value', pref.disk_cache); $('diskCache').setProperty('value', pref.disk_cache);
$('diskCacheExpiryInterval').setProperty('value', pref.disk_cache_ttl); $('diskCacheExpiryInterval').setProperty('value', pref.disk_cache_ttl);
$('diskQueueSize').setProperty('value', (pref.disk_queue_size / 1024)); $('diskQueueSize').setProperty('value', (pref.disk_queue_size / 1024));
$('diskIOType').setProperty('value', pref.disk_io_type);
$('enableOSCache').setProperty('checked', pref.enable_os_cache); $('enableOSCache').setProperty('checked', pref.enable_os_cache);
$('coalesceReadsAndWrites').setProperty('checked', pref.enable_coalesce_read_write); $('coalesceReadsAndWrites').setProperty('checked', pref.enable_coalesce_read_write);
$('pieceExtentAffinity').setProperty('checked', pref.enable_piece_extent_affinity); $('pieceExtentAffinity').setProperty('checked', pref.enable_piece_extent_affinity);
@ -2371,6 +2384,7 @@
settings.set('disk_cache', $('diskCache').getProperty('value')); settings.set('disk_cache', $('diskCache').getProperty('value'));
settings.set('disk_cache_ttl', $('diskCacheExpiryInterval').getProperty('value')); settings.set('disk_cache_ttl', $('diskCacheExpiryInterval').getProperty('value'));
settings.set('disk_queue_size', ($('diskQueueSize').getProperty('value') * 1024)); settings.set('disk_queue_size', ($('diskQueueSize').getProperty('value') * 1024));
settings.set('disk_io_type', $('diskIOType').getProperty('value'));
settings.set('enable_os_cache', $('enableOSCache').getProperty('checked')); settings.set('enable_os_cache', $('enableOSCache').getProperty('checked'));
settings.set('enable_coalesce_read_write', $('coalesceReadsAndWrites').getProperty('checked')); settings.set('enable_coalesce_read_write', $('coalesceReadsAndWrites').getProperty('checked'));
settings.set('enable_piece_extent_affinity', $('pieceExtentAffinity').getProperty('checked')); settings.set('enable_piece_extent_affinity', $('pieceExtentAffinity').getProperty('checked'));

Loading…
Cancel
Save