Browse Source

Add option to control qBittorrent process memory priority

This is to avoid Windows swapping out other application data from
OS cache and put in torrent data which hinders other program
responsiveness.

The default value "Below normal" is choosen because casual users have
other higher priority apps (such as browser) running and they don't
expect OS to swap out its data. Dedicated seeders most probably will not
have other app running on their system and would expect qbt has
priority over other background services.

The option only has effect on Windows >= 8.
adaptive-webui-19844
Chocobo1 5 years ago
parent
commit
0f60121b94
No known key found for this signature in database
GPG Key ID: 210D9C873253A68C
  1. 61
      src/base/bittorrent/session.cpp
  2. 22
      src/base/bittorrent/session.h
  3. 52
      src/gui/advancedsettings.cpp
  4. 2
      src/gui/advancedsettings.h

61
src/base/bittorrent/session.cpp

@ -35,6 +35,7 @@
#include <utility> #include <utility>
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <Windows.h>
#include <wincrypt.h> #include <wincrypt.h>
#include <iphlpapi.h> #include <iphlpapi.h>
#endif #endif
@ -344,6 +345,9 @@ Session::Session(QObject *parent)
return tmp; return tmp;
} }
) )
#if defined(Q_OS_WIN)
, m_OSMemoryPriority(BITTORRENT_KEY("OSMemoryPriority"), OSMemoryPriority::BelowNormal)
#endif
, m_resumeFolderLock {new QFile {this}} , m_resumeFolderLock {new QFile {this}}
, m_refreshTimer {new QTimer {this}} , m_refreshTimer {new QTimer {this}}
, m_seedingLimitTimer {new QTimer {this}} , m_seedingLimitTimer {new QTimer {this}}
@ -930,6 +934,10 @@ void Session::configureComponents()
disableIPFilter(); disableIPFilter();
m_IPFilteringConfigured = true; m_IPFilteringConfigured = true;
} }
#if defined(Q_OS_WIN)
applyOSMemoryPriority();
#endif
} }
void Session::initializeNativeSession() void Session::initializeNativeSession()
@ -2753,6 +2761,59 @@ QStringList Session::bannedIPs() const
return m_bannedIPs; return m_bannedIPs;
} }
#if defined(Q_OS_WIN)
OSMemoryPriority Session::getOSMemoryPriority() const
{
return m_OSMemoryPriority;
}
void Session::setOSMemoryPriority(const OSMemoryPriority priority)
{
if (m_OSMemoryPriority == priority)
return;
m_OSMemoryPriority = priority;
configureDeferred();
}
void Session::applyOSMemoryPriority() const
{
using SETPROCESSINFORMATION = BOOL (WINAPI *)(HANDLE, PROCESS_INFORMATION_CLASS, LPVOID, DWORD);
const auto setProcessInformation = Utils::Misc::loadWinAPI<SETPROCESSINFORMATION>("Kernel32.dll", "SetProcessInformation");
if (!setProcessInformation) // only available on Windows >= 8
return;
#if (_WIN32_WINNT < _WIN32_WINNT_WIN8)
// this dummy struct is required to compile successfully when targeting older Windows version
struct MEMORY_PRIORITY_INFORMATION
{
ULONG MemoryPriority;
};
#endif
MEMORY_PRIORITY_INFORMATION prioInfo {};
switch (getOSMemoryPriority()) {
case OSMemoryPriority::Normal:
default:
prioInfo.MemoryPriority = MEMORY_PRIORITY_NORMAL;
break;
case OSMemoryPriority::BelowNormal:
prioInfo.MemoryPriority = MEMORY_PRIORITY_BELOW_NORMAL;
break;
case OSMemoryPriority::Medium:
prioInfo.MemoryPriority = MEMORY_PRIORITY_MEDIUM;
break;
case OSMemoryPriority::Low:
prioInfo.MemoryPriority = MEMORY_PRIORITY_LOW;
break;
case OSMemoryPriority::VeryLow:
prioInfo.MemoryPriority = MEMORY_PRIORITY_VERY_LOW;
break;
}
setProcessInformation(::GetCurrentProcess(), ProcessMemoryPriority, &prioInfo, sizeof(prioInfo));
}
#endif
int Session::maxConnectionsPerTorrent() const int Session::maxConnectionsPerTorrent() const
{ {
return m_maxConnectionsPerTorrent; return m_maxConnectionsPerTorrent;

22
src/base/bittorrent/session.h

@ -132,6 +132,18 @@ namespace BitTorrent
AntiLeech = 2 AntiLeech = 2
}; };
Q_ENUM_NS(SeedChokingAlgorithm) Q_ENUM_NS(SeedChokingAlgorithm)
#if defined(Q_OS_WIN)
enum class OSMemoryPriority : int
{
Normal = 0,
BelowNormal = 1,
Medium = 2,
Low = 3,
VeryLow = 4
};
Q_ENUM_NS(OSMemoryPriority)
#endif
} }
using namespace SessionSettingsEnums; using namespace SessionSettingsEnums;
@ -387,6 +399,10 @@ namespace BitTorrent
void setTrackerFilteringEnabled(bool enabled); void setTrackerFilteringEnabled(bool enabled);
QStringList bannedIPs() const; QStringList bannedIPs() const;
void setBannedIPs(const QStringList &newList); void setBannedIPs(const QStringList &newList);
#if defined(Q_OS_WIN)
OSMemoryPriority getOSMemoryPriority() const;
void setOSMemoryPriority(OSMemoryPriority priority);
#endif
void startUpTorrents(); void startUpTorrents();
TorrentHandle *findTorrent(const InfoHash &hash) const; TorrentHandle *findTorrent(const InfoHash &hash) const;
@ -530,6 +546,9 @@ namespace BitTorrent
void populateAdditionalTrackers(); void populateAdditionalTrackers();
void enableIPFilter(); void enableIPFilter();
void disableIPFilter(); void disableIPFilter();
#if defined(Q_OS_WIN)
void applyOSMemoryPriority() const;
#endif
bool addTorrent_impl(CreateTorrentParams params, const MagnetUri &magnetUri, bool addTorrent_impl(CreateTorrentParams params, const MagnetUri &magnetUri,
TorrentInfo torrentInfo = TorrentInfo(), TorrentInfo torrentInfo = TorrentInfo(),
@ -661,6 +680,9 @@ namespace BitTorrent
CachedSettingValue<bool> m_isDisableAutoTMMWhenCategorySavePathChanged; CachedSettingValue<bool> m_isDisableAutoTMMWhenCategorySavePathChanged;
CachedSettingValue<bool> m_isTrackerEnabled; CachedSettingValue<bool> m_isTrackerEnabled;
CachedSettingValue<QStringList> m_bannedIPs; CachedSettingValue<QStringList> m_bannedIPs;
#if defined(Q_OS_WIN)
CachedSettingValue<OSMemoryPriority> m_OSMemoryPriority;
#endif
// Order is important. This needs to be declared after its CachedSettingsValue // Order is important. This needs to be declared after its CachedSettingsValue
// counterpart, because it uses it for initialization in the constructor // counterpart, because it uses it for initialization in the constructor

52
src/gui/advancedsettings.cpp

@ -61,6 +61,9 @@ enum AdvSettingsRows
{ {
// qBittorrent section // qBittorrent section
QBITTORRENT_HEADER, QBITTORRENT_HEADER,
#if defined(Q_OS_WIN)
OS_MEMORY_PRIORITY,
#endif
// network interface // network interface
NETWORK_IFACE, NETWORK_IFACE,
//Optional network address //Optional network address
@ -151,6 +154,28 @@ void AdvancedSettings::saveAdvancedSettings()
Preferences *const pref = Preferences::instance(); Preferences *const pref = Preferences::instance();
BitTorrent::Session *const session = BitTorrent::Session::instance(); BitTorrent::Session *const session = BitTorrent::Session::instance();
#if defined(Q_OS_WIN)
BitTorrent::OSMemoryPriority prio = BitTorrent::OSMemoryPriority::Normal;
switch (m_comboBoxOSMemoryPriority.currentIndex()) {
case 0:
default:
prio = BitTorrent::OSMemoryPriority::Normal;
break;
case 1:
prio = BitTorrent::OSMemoryPriority::BelowNormal;
break;
case 2:
prio = BitTorrent::OSMemoryPriority::Medium;
break;
case 3:
prio = BitTorrent::OSMemoryPriority::Low;
break;
case 4:
prio = BitTorrent::OSMemoryPriority::VeryLow;
break;
}
session->setOSMemoryPriority(prio);
#endif
// Async IO threads // Async IO threads
session->setAsyncIOThreads(m_spinBoxAsyncIOThreads.value()); session->setAsyncIOThreads(m_spinBoxAsyncIOThreads.value());
// File pool size // File pool size
@ -321,6 +346,33 @@ void AdvancedSettings::loadAdvancedSettings()
addRow(LIBTORRENT_HEADER, QString("<b>%1</b>").arg(tr("libtorrent Section")), labelLibtorrentLink); addRow(LIBTORRENT_HEADER, QString("<b>%1</b>").arg(tr("libtorrent Section")), labelLibtorrentLink);
static_cast<QLabel *>(cellWidget(LIBTORRENT_HEADER, PROPERTY))->setAlignment(Qt::AlignCenter | Qt::AlignVCenter); static_cast<QLabel *>(cellWidget(LIBTORRENT_HEADER, PROPERTY))->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
#if defined(Q_OS_WIN)
m_comboBoxOSMemoryPriority.addItems({tr("Normal"), tr("Below normal"), tr("Medium"), tr("Low"), tr("Very low")});
int OSMemoryPriorityIndex = 0;
switch (session->getOSMemoryPriority()) {
default:
case BitTorrent::OSMemoryPriority::Normal:
OSMemoryPriorityIndex = 0;
break;
case BitTorrent::OSMemoryPriority::BelowNormal:
OSMemoryPriorityIndex = 1;
break;
case BitTorrent::OSMemoryPriority::Medium:
OSMemoryPriorityIndex = 2;
break;
case BitTorrent::OSMemoryPriority::Low:
OSMemoryPriorityIndex = 3;
break;
case BitTorrent::OSMemoryPriority::VeryLow:
OSMemoryPriorityIndex = 4;
break;
}
m_comboBoxOSMemoryPriority.setCurrentIndex(OSMemoryPriorityIndex);
addRow(OS_MEMORY_PRIORITY, (tr("Process memory priority (Windows >= 8 only)")
+ ' ' + makeLink("https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-memory_priority_information", "(?)"))
, &m_comboBoxOSMemoryPriority);
#endif
// Async IO threads // Async IO threads
m_spinBoxAsyncIOThreads.setMinimum(1); m_spinBoxAsyncIOThreads.setMinimum(1);
m_spinBoxAsyncIOThreads.setMaximum(1024); m_spinBoxAsyncIOThreads.setMaximum(1024);

2
src/gui/advancedsettings.h

@ -71,6 +71,8 @@ private:
// OS dependent settings // OS dependent settings
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS))
QCheckBox m_checkBoxUseIconTheme; QCheckBox m_checkBoxUseIconTheme;
#elif defined(Q_OS_WIN)
QComboBox m_comboBoxOSMemoryPriority;
#endif #endif
}; };

Loading…
Cancel
Save