From cbc89e77ab11a9d1a0d0657b4eb9405e6b641618 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 17 Jan 2017 09:32:58 -0800 Subject: [PATCH] Consume fewer resources in AssetServer when interface is running locally --- assignment-client/src/assets/AssetServer.cpp | 48 +++++++++++++++++ interface/src/main.cpp | 2 +- libraries/shared/src/SharedUtil.cpp | 54 +++++++++++++++++++- libraries/shared/src/SharedUtil.h | 4 ++ 4 files changed, 106 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index 2fbe2f6dfe..69f3d83583 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -12,6 +12,8 @@ #include "AssetServer.h" +#include + #include #include #include @@ -21,6 +23,7 @@ #include #include +#include #include #include "NetworkLogging.h" @@ -30,6 +33,37 @@ const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server"; +bool interfaceRunning() { + bool result = false; + +#ifdef Q_OS_WIN + QSharedMemory sharedMemory { getInterfaceSharedMemoryName() }; + result = sharedMemory.attach(QSharedMemory::ReadOnly); + if (result) { + sharedMemory.detach(); + } +#endif + return result; +} + +void updateConsumedCores() { + static bool wasInterfaceRunning = false; + bool isInterfaceRunning = interfaceRunning(); + // If state is unchanged, return early + if (isInterfaceRunning == wasInterfaceRunning) { + return; + } + + wasInterfaceRunning = isInterfaceRunning; + auto coreCount = std::thread::hardware_concurrency(); + if (isInterfaceRunning) { + coreCount = coreCount > 4 ? 2 : 1; + } + qDebug() << "Setting max consumed cores to " << coreCount; + setMaxCores(coreCount); +} + + AssetServer::AssetServer(ReceivedMessage& message) : ThreadedAssignment(message), _taskPool(this) @@ -45,6 +79,20 @@ AssetServer::AssetServer(ReceivedMessage& message) : packetReceiver.registerListener(PacketType::AssetGetInfo, this, "handleAssetGetInfo"); packetReceiver.registerListener(PacketType::AssetUpload, this, "handleAssetUpload"); packetReceiver.registerListener(PacketType::AssetMappingOperation, this, "handleAssetMappingOperation"); + +#ifdef Q_OS_WIN + updateConsumedCores(); + QTimer* timer = new QTimer(this); + auto timerConnection = connect(timer, &QTimer::timeout, [] { + updateConsumedCores(); + }); + connect(qApp, &QCoreApplication::aboutToQuit, [this, timerConnection] { + disconnect(timerConnection); + }); + timer->setInterval(1000); + timer->setTimerType(Qt::CoarseTimer); + timer->start(); +#endif } void AssetServer::run() { diff --git a/interface/src/main.cpp b/interface/src/main.cpp index c83f7a989c..d33dba535e 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -56,7 +56,7 @@ int main(int argc, const char* argv[]) { QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN); QCoreApplication::setApplicationVersion(BuildInfo::VERSION); - QString applicationName = "High Fidelity Interface - " + qgetenv("USERNAME"); + const QString& applicationName = getInterfaceSharedMemoryName(); bool instanceMightBeRunning = true; diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 89116aa924..4b8699befd 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include @@ -1022,4 +1024,54 @@ bool getProcessorInfo(ProcessorInfo& info) { #endif return false; -} \ No newline at end of file +} + + +const QString& getInterfaceSharedMemoryName() { + static const QString applicationName = "High Fidelity Interface - " + qgetenv("USERNAME"); + return applicationName; +} + +const std::vector& getAvailableCores() { + static std::vector availableCores; +#ifdef Q_OS_WIN + static std::once_flag once; + std::call_once(once, [&] { + DWORD_PTR defaultProcessAffinity = 0, defaultSystemAffinity = 0; + HANDLE process = GetCurrentProcess(); + GetProcessAffinityMask(process, &defaultProcessAffinity, &defaultSystemAffinity); + for (uint64_t i = 0; i < sizeof(DWORD_PTR) * 8; ++i) { + DWORD_PTR coreMask = 1; + coreMask <<= i; + if (0 != (defaultSystemAffinity & coreMask)) { + availableCores.push_back(i); + } + } + }); +#endif + return availableCores; +} + +void setMaxCores(uint8_t maxCores) { +#ifdef Q_OS_WIN + HANDLE process = GetCurrentProcess(); + auto availableCores = getAvailableCores(); + if (availableCores.size() <= maxCores) { + DWORD_PTR currentProcessAffinity = 0, currentSystemAffinity = 0; + GetProcessAffinityMask(process, ¤tProcessAffinity, ¤tSystemAffinity); + SetProcessAffinityMask(GetCurrentProcess(), currentSystemAffinity); + return; + } + + DWORD_PTR newProcessAffinity = 0; + while (maxCores) { + int index = randIntInRange(0, (int)availableCores.size() - 1); + DWORD_PTR coreMask = 1; + coreMask <<= availableCores[index]; + newProcessAffinity |= coreMask; + availableCores.erase(availableCores.begin() + index); + maxCores--; + } + SetProcessAffinityMask(process, newProcessAffinity); +#endif +} diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 77204c9608..0f30842f47 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -231,4 +231,8 @@ struct ProcessorInfo { bool getProcessorInfo(ProcessorInfo& info); +const QString& getInterfaceSharedMemoryName(); + +void setMaxCores(uint8_t maxCores); + #endif // hifi_SharedUtil_h