Allow to limit max memory working set size

PR #16485.
This commit is contained in:
Vladimir Golovnev 2022-03-01 16:42:25 +03:00 committed by GitHub
parent 7ea827f8d3
commit 299f981441
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 0 deletions

View file

@ -64,6 +64,7 @@
#include "base/bittorrent/session.h"
#include "base/bittorrent/torrent.h"
#include "base/exceptions.h"
#include "base/global.h"
#include "base/iconprovider.h"
#include "base/logger.h"
#include "base/net/downloadmanager.h"
@ -121,6 +122,9 @@ Application::Application(int &argc, char **argv)
, m_running(false)
, m_shutdownAct(ShutdownDialogAction::Exit)
, m_commandLineArgs(parseCommandLine(this->arguments()))
#ifdef Q_OS_WIN
, m_storeMemoryWorkingSetLimit(SETTINGS_KEY("MemoryWorkingSetLimit"))
#endif
, m_storeFileLoggerEnabled(FILELOGGER_SETTINGS_KEY("Enabled"))
, m_storeFileLoggerBackup(FILELOGGER_SETTINGS_KEY("Backup"))
, m_storeFileLoggerDeleteOld(FILELOGGER_SETTINGS_KEY("DeleteOld"))
@ -204,6 +208,22 @@ const QBtCommandLineParameters &Application::commandLineArgs() const
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
{
return m_storeFileLoggerEnabled.get(true);
@ -602,6 +622,10 @@ void Application::processParams(const QStringList &params)
int Application::exec(const QStringList &params)
{
#ifdef Q_OS_WIN
applyMemoryWorkingSetLimit();
#endif
Net::ProxyConfigurationManager::initInstance();
Net::DownloadManager::initInstance();
IconProvider::initInstance();
@ -771,6 +795,29 @@ void Application::shutdownCleanup(QSessionManager &manager)
}
#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()
{
// cleanup() can be called multiple times during shutdown. We only need it once.