mirror of
https://github.com/LibreOffice/online.git
synced 2025-07-25 16:04:48 +00:00
wsd: reduce memory load only when the footprint changes
Update the network interval when updating the memory interval, since we currently don't support changing the network interval. Also make the default memory and network interval twice that of the cpu interval explicitly. Reduce logging noise a bit without losing information. And some const-correctness and other cleanups. Change-Id: I313fb2882675f560091e5113dbdcbdef269828e2 Reviewed-on: https://gerrit.libreoffice.org/49571 Reviewed-by: Ashod Nakashian <ashnakash@gmail.com> Tested-by: Ashod Nakashian <ashnakash@gmail.com>
This commit is contained in:

committed by
Ashod Nakashian

parent
2562d8919a
commit
88619a323f
@ -333,9 +333,9 @@ Admin::Admin() :
|
|||||||
_lastJiffies(0),
|
_lastJiffies(0),
|
||||||
_lastSentCount(0),
|
_lastSentCount(0),
|
||||||
_lastRecvCount(0),
|
_lastRecvCount(0),
|
||||||
_memStatsTaskIntervalMs(5000),
|
_cpuStatsTaskIntervalMs(DefStatsIntervalMs),
|
||||||
_cpuStatsTaskIntervalMs(2000),
|
_memStatsTaskIntervalMs(DefStatsIntervalMs * 2),
|
||||||
_networkStatsIntervalMs(5000)
|
_netStatsTaskIntervalMs(DefStatsIntervalMs * 2)
|
||||||
{
|
{
|
||||||
LOG_INF("Admin ctor.");
|
LOG_INF("Admin ctor.");
|
||||||
|
|
||||||
@ -371,18 +371,18 @@ void Admin::pollingThread()
|
|||||||
|
|
||||||
while (!_stop && !TerminationFlag && !ShutdownRequestFlag)
|
while (!_stop && !TerminationFlag && !ShutdownRequestFlag)
|
||||||
{
|
{
|
||||||
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
|
const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
int cpuWait = _cpuStatsTaskIntervalMs -
|
int cpuWait = _cpuStatsTaskIntervalMs -
|
||||||
std::chrono::duration_cast<std::chrono::milliseconds>(now - lastCPU).count();
|
std::chrono::duration_cast<std::chrono::milliseconds>(now - lastCPU).count();
|
||||||
if (cpuWait <= MinStatsIntervalMs / 2) // Close enough
|
if (cpuWait <= MinStatsIntervalMs / 2) // Close enough
|
||||||
{
|
{
|
||||||
const size_t currentJiffies = getTotalCpuUsage();
|
const size_t currentJiffies = getTotalCpuUsage();
|
||||||
size_t cpuPercent = 100 * 1000 * currentJiffies / (sysconf (_SC_CLK_TCK) * _cpuStatsTaskIntervalMs);
|
const size_t cpuPercent = 100 * 1000 * currentJiffies / (sysconf (_SC_CLK_TCK) * _cpuStatsTaskIntervalMs);
|
||||||
_model.addCpuStats(cpuPercent);
|
_model.addCpuStats(cpuPercent);
|
||||||
|
|
||||||
lastCPU = now;
|
|
||||||
cpuWait += _cpuStatsTaskIntervalMs;
|
cpuWait += _cpuStatsTaskIntervalMs;
|
||||||
|
lastCPU = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
int memWait = _memStatsTaskIntervalMs -
|
int memWait = _memStatsTaskIntervalMs -
|
||||||
@ -390,41 +390,43 @@ void Admin::pollingThread()
|
|||||||
if (memWait <= MinStatsIntervalMs / 2) // Close enough
|
if (memWait <= MinStatsIntervalMs / 2) // Close enough
|
||||||
{
|
{
|
||||||
const size_t totalMem = getTotalMemoryUsage();
|
const size_t totalMem = getTotalMemoryUsage();
|
||||||
|
_model.addMemStats(totalMem);
|
||||||
|
|
||||||
if (totalMem != _lastTotalMemory)
|
if (totalMem != _lastTotalMemory)
|
||||||
{
|
{
|
||||||
LOG_TRC("Total memory used: " << totalMem << " KB.");
|
// If our total memory consumption is above limit, cleanup
|
||||||
|
triggerMemoryCleanup(totalMem);
|
||||||
|
|
||||||
_lastTotalMemory = totalMem;
|
_lastTotalMemory = totalMem;
|
||||||
}
|
}
|
||||||
|
|
||||||
_model.addMemStats(totalMem);
|
|
||||||
|
|
||||||
lastMem = now;
|
|
||||||
memWait += _memStatsTaskIntervalMs;
|
memWait += _memStatsTaskIntervalMs;
|
||||||
|
lastMem = now;
|
||||||
// If our total memory consumption is above limit, cleanup
|
|
||||||
triggerMemoryCleanup(totalMem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int netWait = _networkStatsIntervalMs -
|
int netWait = _netStatsTaskIntervalMs -
|
||||||
std::chrono::duration_cast<std::chrono::milliseconds>(now - lastNet).count();
|
std::chrono::duration_cast<std::chrono::milliseconds>(now - lastNet).count();
|
||||||
if (netWait <= MinStatsIntervalMs / 2) // Close enough
|
if (netWait <= MinStatsIntervalMs / 2) // Close enough
|
||||||
{
|
{
|
||||||
uint64_t sentCount = _model.getSentBytesTotal();
|
const uint64_t sentCount = _model.getSentBytesTotal();
|
||||||
uint64_t recvCount = _model.getRecvBytesTotal();
|
const uint64_t recvCount = _model.getRecvBytesTotal();
|
||||||
|
|
||||||
_model.addSentStats(sentCount - _lastSentCount);
|
_model.addSentStats(sentCount - _lastSentCount);
|
||||||
_model.addRecvStats(recvCount - _lastRecvCount);
|
_model.addRecvStats(recvCount - _lastRecvCount);
|
||||||
|
|
||||||
LOG_TRC("Total Data sent: " << sentCount << ", recv: " << recvCount);
|
if (_lastRecvCount != recvCount || _lastSentCount != sentCount)
|
||||||
_lastRecvCount = recvCount;
|
{
|
||||||
_lastSentCount = sentCount;
|
LOG_TRC("Total Data sent: " << sentCount << ", recv: " << recvCount);
|
||||||
|
_lastRecvCount = recvCount;
|
||||||
|
_lastSentCount = sentCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
netWait += _netStatsTaskIntervalMs;
|
||||||
lastNet = now;
|
lastNet = now;
|
||||||
netWait += _networkStatsIntervalMs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle websockets & other work.
|
// Handle websockets & other work.
|
||||||
const int timeout = std::max(std::min(std::min(cpuWait, memWait), netWait), MinStatsIntervalMs);
|
const int timeout = capAndRoundInterval(std::min(std::min(cpuWait, memWait), netWait));
|
||||||
LOG_TRC("Admin poll for " << timeout << "ms.");
|
LOG_TRC("Admin poll for " << timeout << "ms.");
|
||||||
poll(timeout);
|
poll(timeout);
|
||||||
}
|
}
|
||||||
@ -453,14 +455,16 @@ void Admin::rmDoc(const std::string& docKey)
|
|||||||
|
|
||||||
void Admin::rescheduleMemTimer(unsigned interval)
|
void Admin::rescheduleMemTimer(unsigned interval)
|
||||||
{
|
{
|
||||||
_memStatsTaskIntervalMs = std::max<int>(interval, MinStatsIntervalMs);
|
_memStatsTaskIntervalMs = capAndRoundInterval(interval);
|
||||||
LOG_INF("Memory stats interval changed - New interval: " << _memStatsTaskIntervalMs);
|
LOG_INF("Memory stats interval changed - New interval: " << _memStatsTaskIntervalMs);
|
||||||
|
_netStatsTaskIntervalMs = capAndRoundInterval(interval); // Until we support modifying this.
|
||||||
|
LOG_INF("Network stats interval changed - New interval: " << _netStatsTaskIntervalMs);
|
||||||
wakeup();
|
wakeup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Admin::rescheduleCpuTimer(unsigned interval)
|
void Admin::rescheduleCpuTimer(unsigned interval)
|
||||||
{
|
{
|
||||||
_cpuStatsTaskIntervalMs = std::max<int>(interval, MinStatsIntervalMs);
|
_cpuStatsTaskIntervalMs = capAndRoundInterval(interval);
|
||||||
LOG_INF("CPU stats interval changed - New interval: " << _cpuStatsTaskIntervalMs);
|
LOG_INF("CPU stats interval changed - New interval: " << _cpuStatsTaskIntervalMs);
|
||||||
wakeup();
|
wakeup();
|
||||||
}
|
}
|
||||||
@ -485,7 +489,7 @@ size_t Admin::getTotalCpuUsage()
|
|||||||
const size_t wsdJ = Util::getCpuUsage(Poco::Process::id());
|
const size_t wsdJ = Util::getCpuUsage(Poco::Process::id());
|
||||||
const size_t kitsJ = _model.getKitsJiffies();
|
const size_t kitsJ = _model.getKitsJiffies();
|
||||||
|
|
||||||
if(_lastJiffies == 0)
|
if (_lastJiffies == 0)
|
||||||
{
|
{
|
||||||
_lastJiffies = forkitJ + wsdJ;
|
_lastJiffies = forkitJ + wsdJ;
|
||||||
return 0;
|
return 0;
|
||||||
@ -509,7 +513,7 @@ unsigned Admin::getCpuStatsInterval()
|
|||||||
|
|
||||||
unsigned Admin::getNetStatsInterval()
|
unsigned Admin::getNetStatsInterval()
|
||||||
{
|
{
|
||||||
return _networkStatsIntervalMs;
|
return _netStatsTaskIntervalMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
AdminModel& Admin::getModel()
|
AdminModel& Admin::getModel()
|
||||||
@ -546,7 +550,7 @@ void Admin::notifyForkit()
|
|||||||
LOG_INF("Forkit write pipe not set (yet).");
|
LOG_INF("Forkit write pipe not set (yet).");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Admin::triggerMemoryCleanup(size_t totalMem)
|
void Admin::triggerMemoryCleanup(const size_t totalMem)
|
||||||
{
|
{
|
||||||
// Trigger mem cleanup when we are consuming too much memory (as configured by sysadmin)
|
// Trigger mem cleanup when we are consuming too much memory (as configured by sysadmin)
|
||||||
const auto memLimit = LOOLWSD::getConfigValue<double>("memproportion", 0.0);
|
const auto memLimit = LOOLWSD::getConfigValue<double>("memproportion", 0.0);
|
||||||
|
@ -126,6 +126,14 @@ private:
|
|||||||
/// under @hardModeLimit
|
/// under @hardModeLimit
|
||||||
void triggerMemoryCleanup(size_t hardModeLimit);
|
void triggerMemoryCleanup(size_t hardModeLimit);
|
||||||
|
|
||||||
|
/// Round the interval up to multiples of MinStatsIntervalMs.
|
||||||
|
/// This is to avoid arbitrarily small intervals that hammer the server.
|
||||||
|
static int capAndRoundInterval(const unsigned interval)
|
||||||
|
{
|
||||||
|
const int value = std::max<int>(interval, MinStatsIntervalMs);
|
||||||
|
return ((value + MinStatsIntervalMs - 1) / MinStatsIntervalMs) * MinStatsIntervalMs;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// The model is accessed only during startup & in
|
/// The model is accessed only during startup & in
|
||||||
/// the Admin Poll thread.
|
/// the Admin Poll thread.
|
||||||
@ -139,13 +147,14 @@ private:
|
|||||||
size_t _totalSysMemKb;
|
size_t _totalSysMemKb;
|
||||||
size_t _totalAvailMemKb;
|
size_t _totalAvailMemKb;
|
||||||
|
|
||||||
std::atomic<int> _memStatsTaskIntervalMs;
|
|
||||||
std::atomic<int> _cpuStatsTaskIntervalMs;
|
std::atomic<int> _cpuStatsTaskIntervalMs;
|
||||||
std::atomic<int> _networkStatsIntervalMs;
|
std::atomic<int> _memStatsTaskIntervalMs;
|
||||||
|
std::atomic<int> _netStatsTaskIntervalMs;
|
||||||
DocProcSettings _defDocProcSettings;
|
DocProcSettings _defDocProcSettings;
|
||||||
|
|
||||||
// Don't update any more frequently than this since it's excessive.
|
// Don't update any more frequently than this since it's excessive.
|
||||||
const int MinStatsIntervalMs = 50;
|
static const int MinStatsIntervalMs = 50;
|
||||||
|
static const int DefStatsIntervalMs = 2500;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user