Browse Source

Allow to limit max memory working set size

PR #16485.
adaptive-webui-19844
Vladimir Golovnev 3 years ago committed by GitHub
parent
commit
299f981441
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 47
      src/app/application.cpp
  2. 11
      src/app/application.h
  3. 12
      src/gui/advancedsettings.cpp
  4. 1
      src/gui/advancedsettings.h

47
src/app/application.cpp

@ -64,6 +64,7 @@
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/bittorrent/torrent.h" #include "base/bittorrent/torrent.h"
#include "base/exceptions.h" #include "base/exceptions.h"
#include "base/global.h"
#include "base/iconprovider.h" #include "base/iconprovider.h"
#include "base/logger.h" #include "base/logger.h"
#include "base/net/downloadmanager.h" #include "base/net/downloadmanager.h"
@ -121,6 +122,9 @@ Application::Application(int &argc, char **argv)
, m_running(false) , m_running(false)
, m_shutdownAct(ShutdownDialogAction::Exit) , m_shutdownAct(ShutdownDialogAction::Exit)
, m_commandLineArgs(parseCommandLine(this->arguments())) , m_commandLineArgs(parseCommandLine(this->arguments()))
#ifdef Q_OS_WIN
, m_storeMemoryWorkingSetLimit(SETTINGS_KEY("MemoryWorkingSetLimit"))
#endif
, m_storeFileLoggerEnabled(FILELOGGER_SETTINGS_KEY("Enabled")) , m_storeFileLoggerEnabled(FILELOGGER_SETTINGS_KEY("Enabled"))
, m_storeFileLoggerBackup(FILELOGGER_SETTINGS_KEY("Backup")) , m_storeFileLoggerBackup(FILELOGGER_SETTINGS_KEY("Backup"))
, m_storeFileLoggerDeleteOld(FILELOGGER_SETTINGS_KEY("DeleteOld")) , m_storeFileLoggerDeleteOld(FILELOGGER_SETTINGS_KEY("DeleteOld"))
@ -204,6 +208,22 @@ const QBtCommandLineParameters &Application::commandLineArgs() const
return m_commandLineArgs; return m_commandLineArgs;
} }
#ifdef Q_OS_WIN
int Application::memoryWorkingSetLimit() const
{
return m_storeMemoryWorkingSetLimit.get(512);
}
void Application::setMemoryWorkingSetLimit(const int size)
{
if (size == memoryWorkingSetLimit())
return;
m_storeMemoryWorkingSetLimit = size;
applyMemoryWorkingSetLimit();
}
#endif
bool Application::isFileLoggerEnabled() const bool Application::isFileLoggerEnabled() const
{ {
return m_storeFileLoggerEnabled.get(true); return m_storeFileLoggerEnabled.get(true);
@ -602,6 +622,10 @@ void Application::processParams(const QStringList &params)
int Application::exec(const QStringList &params) int Application::exec(const QStringList &params)
{ {
#ifdef Q_OS_WIN
applyMemoryWorkingSetLimit();
#endif
Net::ProxyConfigurationManager::initInstance(); Net::ProxyConfigurationManager::initInstance();
Net::DownloadManager::initInstance(); Net::DownloadManager::initInstance();
IconProvider::initInstance(); IconProvider::initInstance();
@ -771,6 +795,29 @@ void Application::shutdownCleanup(QSessionManager &manager)
} }
#endif #endif
#ifdef Q_OS_WIN
void Application::applyMemoryWorkingSetLimit()
{
const int UNIT_SIZE = 1024 * 1024; // MiB
const SIZE_T maxSize = memoryWorkingSetLimit() * UNIT_SIZE;
const SIZE_T minSize = std::min<SIZE_T>((64 * UNIT_SIZE), (maxSize / 2));
if (!::SetProcessWorkingSetSizeEx(::GetCurrentProcess(), minSize, maxSize, QUOTA_LIMITS_HARDWS_MAX_ENABLE))
{
const DWORD errorCode = ::GetLastError();
QString message;
LPVOID lpMsgBuf = nullptr;
if (::FormatMessageW((FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS)
, nullptr, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPWSTR>(&lpMsgBuf), 0, nullptr))
{
message = QString::fromWCharArray(reinterpret_cast<LPWSTR>(lpMsgBuf)).trimmed();
::LocalFree(lpMsgBuf);
}
LogMsg(tr("Failed to set physical memory (RAM) usage limit. Error code: %1. Error message: \"%2\"")
.arg(QString::number(errorCode), message), Log::WARNING);
}
}
#endif
void Application::cleanup() void Application::cleanup()
{ {
// cleanup() can be called multiple times during shutdown. We only need it once. // cleanup() can be called multiple times during shutdown. We only need it once.

11
src/app/application.h

@ -89,6 +89,11 @@ public:
const QBtCommandLineParameters &commandLineArgs() const; const QBtCommandLineParameters &commandLineArgs() const;
#ifdef Q_OS_WIN
int memoryWorkingSetLimit() const;
void setMemoryWorkingSetLimit(int size);
#endif
// FileLogger properties // FileLogger properties
bool isFileLoggerEnabled() const; bool isFileLoggerEnabled() const;
void setFileLoggerEnabled(bool value); void setFileLoggerEnabled(bool value);
@ -122,6 +127,9 @@ private slots:
#endif #endif
private: private:
#ifdef Q_OS_WIN
void applyMemoryWorkingSetLimit();
#endif
void initializeTranslation(); void initializeTranslation();
void processParams(const QStringList &params); void processParams(const QStringList &params);
void runExternalProgram(const BitTorrent::Torrent *torrent) const; void runExternalProgram(const BitTorrent::Torrent *torrent) const;
@ -147,6 +155,9 @@ private:
QTranslator m_translator; QTranslator m_translator;
QStringList m_paramsQueue; QStringList m_paramsQueue;
#ifdef Q_OS_WIN
SettingValue<int> m_storeMemoryWorkingSetLimit;
#endif
SettingValue<bool> m_storeFileLoggerEnabled; SettingValue<bool> m_storeFileLoggerEnabled;
SettingValue<bool> m_storeFileLoggerBackup; SettingValue<bool> m_storeFileLoggerBackup;
SettingValue<bool> m_storeFileLoggerDeleteOld; SettingValue<bool> m_storeFileLoggerDeleteOld;

12
src/gui/advancedsettings.cpp

@ -64,6 +64,7 @@ namespace
RESUME_DATA_STORAGE, RESUME_DATA_STORAGE,
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
OS_MEMORY_PRIORITY, OS_MEMORY_PRIORITY,
MEMORY_WORKING_SET_LIMIT,
#endif #endif
// network interface // network interface
NETWORK_IFACE, NETWORK_IFACE,
@ -198,6 +199,8 @@ void AdvancedSettings::saveAdvancedSettings()
break; break;
} }
session->setOSMemoryPriority(prio); session->setOSMemoryPriority(prio);
static_cast<Application *>(QCoreApplication::instance())->setMemoryWorkingSetLimit(m_spinBoxMemoryWorkingSetLimit.value());
#endif #endif
// Async IO threads // Async IO threads
session->setAsyncIOThreads(m_spinBoxAsyncIOThreads.value()); session->setAsyncIOThreads(m_spinBoxAsyncIOThreads.value());
@ -442,6 +445,15 @@ void AdvancedSettings::loadAdvancedSettings()
addRow(OS_MEMORY_PRIORITY, (tr("Process memory priority (Windows >= 8 only)") 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", "(?)")) + ' ' + makeLink("https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-memory_priority_information", "(?)"))
, &m_comboBoxOSMemoryPriority); , &m_comboBoxOSMemoryPriority);
m_spinBoxMemoryWorkingSetLimit.setMinimum(1);
m_spinBoxMemoryWorkingSetLimit.setMaximum(std::numeric_limits<int>::max());
m_spinBoxMemoryWorkingSetLimit.setSuffix(tr(" MiB"));
m_spinBoxMemoryWorkingSetLimit.setValue(static_cast<Application *>(QCoreApplication::instance())->memoryWorkingSetLimit());
addRow(MEMORY_WORKING_SET_LIMIT, (tr("Physical memory (RAM) usage limit")
+ ' ' + makeLink("https://wikipedia.org/wiki/Working_set", "(?)"))
, &m_spinBoxMemoryWorkingSetLimit);
#endif #endif
// Async IO threads // Async IO threads

1
src/gui/advancedsettings.h

@ -82,6 +82,7 @@ private:
// OS dependent settings // OS dependent settings
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
QComboBox m_comboBoxOSMemoryPriority; QComboBox m_comboBoxOSMemoryPriority;
QSpinBox m_spinBoxMemoryWorkingSetLimit;
#endif #endif
#ifndef Q_OS_MACOS #ifndef Q_OS_MACOS

Loading…
Cancel
Save