Commit 8533a79b authored by Zack Galbreath's avatar Zack Galbreath Committed by Brad King

SystemInformation: Add GetLoadAverage() method

Implement on platforms with getloadavg() available.  Also implement
on Windows using an approach like that described here:

 http://stackoverflow.com/questions/23143693/retrieving-cpu-load-percent-total-in-windows-with-c

Co-Author: Betsy McPhail <betsy.mcphail@kitware.com>
Co-Author: Brad King <brad.king@kitware.com>
Change-Id: I5c50b964a05ece97e88f246df532ed6881bf2dce
parent 61e0419f
......@@ -786,6 +786,15 @@ IF(KWSYS_USE_SystemInformation)
SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS KWSYS_BUILD_SHARED=1)
ENDIF()
IF(UNIX AND NOT CYGWIN)
KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_GETLOADAVG
"Checking whether CXX compiler has getloadavg" DIRECT)
IF(KWSYS_CXX_HAS_GETLOADAVG)
SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS KWSYS_CXX_HAS_GETLOADAVG=1)
ENDIF()
ENDIF()
ENDIF()
#-----------------------------------------------------------------------------
......
......@@ -81,6 +81,11 @@ typedef int siginfo_t;
# include <errno.h> // extern int errno;
#endif
#if defined (__CYGWIN__) && !defined(_WIN32)
# include <windows.h>
# undef _WIN32
#endif
#ifdef __FreeBSD__
# include <sys/sysctl.h>
# include <fenv.h>
......@@ -366,6 +371,8 @@ public:
const char *procLimitEnvVarName);
LongLong GetProcMemoryUsed();
double GetLoadAverage();
// enable/disable stack trace signal handler.
static
void SetStackTraceOnError(int enable);
......@@ -820,6 +827,11 @@ SystemInformation::LongLong SystemInformation::GetProcMemoryUsed()
return this->Implementation->GetProcMemoryUsed();
}
double SystemInformation::GetLoadAverage()
{
return this->Implementation->GetLoadAverage();
}
SystemInformation::LongLong SystemInformation::GetProcessId()
{
return this->Implementation->GetProcessId();
......@@ -1490,6 +1502,60 @@ void SymbolProperties::Initialize(void *address)
}
#endif // don't define this class if we're not using it
// --------------------------------------------------------------------------
#if defined(_WIN32) || defined(__CYGWIN__)
# define KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes
#endif
#if defined(_MSC_VER) && _MSC_VER < 1310
# undef KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes
#endif
#if defined(KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes)
double calculateCPULoad(unsigned __int64 idleTicks,
unsigned __int64 totalTicks)
{
static double previousLoad = -0.0;
static unsigned __int64 previousIdleTicks = 0;
static unsigned __int64 previousTotalTicks = 0;
unsigned __int64 const idleTicksSinceLastTime =
idleTicks - previousIdleTicks;
unsigned __int64 const totalTicksSinceLastTime =
totalTicks - previousTotalTicks;
double load;
if (previousTotalTicks == 0 || totalTicksSinceLastTime == 0)
{
// No new information. Use previous result.
load = previousLoad;
}
else
{
// Calculate load since last time.
load = 1.0 - double(idleTicksSinceLastTime) / totalTicksSinceLastTime;
// Smooth if possible.
if (previousLoad > 0)
{
load = 0.25 * load + 0.75 * previousLoad;
}
}
previousLoad = load;
previousIdleTicks = idleTicks;
previousTotalTicks = totalTicks;
return load;
}
unsigned __int64 fileTimeToUInt64(FILETIME const& ft)
{
LARGE_INTEGER out;
out.HighPart = ft.dwHighDateTime;
out.LowPart = ft.dwLowDateTime;
return out.QuadPart;
}
#endif
} // anonymous namespace
......@@ -3612,6 +3678,38 @@ SystemInformationImplementation::GetProcMemoryUsed()
#endif
}
double SystemInformationImplementation::GetLoadAverage()
{
#if defined(KWSYS_CXX_HAS_GETLOADAVG)
double loadavg[3] = { 0.0, 0.0, 0.0 };
if (getloadavg(loadavg, 3) > 0)
{
return loadavg[0];
}
return -0.0;
#elif defined(KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes)
// Old windows.h headers do not provide GetSystemTimes.
typedef BOOL (WINAPI *GetSystemTimesType)(LPFILETIME, LPFILETIME,
LPFILETIME);
static GetSystemTimesType pGetSystemTimes =
(GetSystemTimesType)GetProcAddress(GetModuleHandleW(L"kernel32"),
"GetSystemTimes");
FILETIME idleTime, kernelTime, userTime;
if (pGetSystemTimes && pGetSystemTimes(&idleTime, &kernelTime, &userTime))
{
unsigned __int64 const idleTicks =
fileTimeToUInt64(idleTime);
unsigned __int64 const totalTicks =
fileTimeToUInt64(kernelTime) + fileTimeToUInt64(userTime);
return calculateCPULoad(idleTicks, totalTicks) * GetNumberOfPhysicalCPU();
}
return -0.0;
#else
// Not implemented on this platform.
return -0.0;
#endif
}
/**
Get the process id of the running process.
*/
......
......@@ -130,6 +130,10 @@ public:
// Get system RAM used by this process id in units of KiB.
LongLong GetProcMemoryUsed();
// Return the load average of the machine or -0.0 if it cannot
// be determined.
double GetLoadAverage();
// enable/disable stack trace signal handler. In order to
// produce an informative stack trace the application should
// be dynamically linked and compiled with debug symbols.
......
......@@ -452,6 +452,19 @@ int main()
}
#endif
#ifdef TEST_KWSYS_CXX_HAS_GETLOADAVG
// Match feature definitions from SystemInformation.cxx
#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
# define _GNU_SOURCE
#endif
#include <stdlib.h>
int main()
{
double loadavg[3] = { 0.0, 0.0, 0.0 };
return getloadavg(loadavg, 3);
}
#endif
#ifdef TEST_KWSYS_CXX_HAS_RLIMIT64
# if defined(KWSYS_HAS_LFS)
# define _LARGEFILE_SOURCE
......
......@@ -87,6 +87,7 @@ int testSystemInformation(int, char*[])
printMethod3(info, GetProcMemoryAvailable("KWSHL","KWSPL"), "KiB");
printMethod3(info, GetHostMemoryUsed(), "KiB");
printMethod3(info, GetProcMemoryUsed(), "KiB");
printMethod(info, GetLoadAverage);
for (long int i = 0; i <= 31; i++)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment