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.
This commit is contained in:
Chocobo1 2019-09-28 14:21:53 +08:00
parent c1e0207454
commit 0f60121b94
No known key found for this signature in database
GPG Key ID: 210D9C873253A68C
4 changed files with 137 additions and 0 deletions

View File

@ -35,6 +35,7 @@
#include <utility>
#ifdef Q_OS_WIN
#include <Windows.h>
#include <wincrypt.h>
#include <iphlpapi.h>
#endif
@ -344,6 +345,9 @@ Session::Session(QObject *parent)
return tmp;
}
)
#if defined(Q_OS_WIN)
, m_OSMemoryPriority(BITTORRENT_KEY("OSMemoryPriority"), OSMemoryPriority::BelowNormal)
#endif
, m_resumeFolderLock {new QFile {this}}
, m_refreshTimer {new QTimer {this}}
, m_seedingLimitTimer {new QTimer {this}}
@ -930,6 +934,10 @@ void Session::configureComponents()
disableIPFilter();
m_IPFilteringConfigured = true;
}
#if defined(Q_OS_WIN)
applyOSMemoryPriority();
#endif
}
void Session::initializeNativeSession()
@ -2753,6 +2761,59 @@ QStringList Session::bannedIPs() const
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
{
return m_maxConnectionsPerTorrent;

View File

@ -132,6 +132,18 @@ namespace BitTorrent
AntiLeech = 2
};
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;
@ -387,6 +399,10 @@ namespace BitTorrent
void setTrackerFilteringEnabled(bool enabled);
QStringList bannedIPs() const;
void setBannedIPs(const QStringList &newList);
#if defined(Q_OS_WIN)
OSMemoryPriority getOSMemoryPriority() const;
void setOSMemoryPriority(OSMemoryPriority priority);
#endif
void startUpTorrents();
TorrentHandle *findTorrent(const InfoHash &hash) const;
@ -530,6 +546,9 @@ namespace BitTorrent
void populateAdditionalTrackers();
void enableIPFilter();
void disableIPFilter();
#if defined(Q_OS_WIN)
void applyOSMemoryPriority() const;
#endif
bool addTorrent_impl(CreateTorrentParams params, const MagnetUri &magnetUri,
TorrentInfo torrentInfo = TorrentInfo(),
@ -661,6 +680,9 @@ namespace BitTorrent
CachedSettingValue<bool> m_isDisableAutoTMMWhenCategorySavePathChanged;
CachedSettingValue<bool> m_isTrackerEnabled;
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
// counterpart, because it uses it for initialization in the constructor

View File

@ -61,6 +61,9 @@ enum AdvSettingsRows
{
// qBittorrent section
QBITTORRENT_HEADER,
#if defined(Q_OS_WIN)
OS_MEMORY_PRIORITY,
#endif
// network interface
NETWORK_IFACE,
//Optional network address
@ -151,6 +154,28 @@ void AdvancedSettings::saveAdvancedSettings()
Preferences *const pref = Preferences::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
session->setAsyncIOThreads(m_spinBoxAsyncIOThreads.value());
// File pool size
@ -321,6 +346,33 @@ void AdvancedSettings::loadAdvancedSettings()
addRow(LIBTORRENT_HEADER, QString("<b>%1</b>").arg(tr("libtorrent Section")), labelLibtorrentLink);
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
m_spinBoxAsyncIOThreads.setMinimum(1);
m_spinBoxAsyncIOThreads.setMaximum(1024);

View File

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