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

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) ...@@ -786,6 +786,15 @@ IF(KWSYS_USE_SystemInformation)
SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS KWSYS_BUILD_SHARED=1) COMPILE_DEFINITIONS KWSYS_BUILD_SHARED=1)
ENDIF() 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() ENDIF()
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
......
...@@ -81,6 +81,11 @@ typedef int siginfo_t; ...@@ -81,6 +81,11 @@ typedef int siginfo_t;
# include <errno.h> // extern int errno; # include <errno.h> // extern int errno;
#endif #endif
#if defined (__CYGWIN__) && !defined(_WIN32)
# include <windows.h>
# undef _WIN32
#endif
#ifdef __FreeBSD__ #ifdef __FreeBSD__
# include <sys/sysctl.h> # include <sys/sysctl.h>
# include <fenv.h> # include <fenv.h>
...@@ -366,6 +371,8 @@ public: ...@@ -366,6 +371,8 @@ public:
const char *procLimitEnvVarName); const char *procLimitEnvVarName);
LongLong GetProcMemoryUsed(); LongLong GetProcMemoryUsed();
double GetLoadAverage();
// enable/disable stack trace signal handler. // enable/disable stack trace signal handler.
static static
void SetStackTraceOnError(int enable); void SetStackTraceOnError(int enable);
...@@ -820,6 +827,11 @@ SystemInformation::LongLong SystemInformation::GetProcMemoryUsed() ...@@ -820,6 +827,11 @@ SystemInformation::LongLong SystemInformation::GetProcMemoryUsed()
return this->Implementation->GetProcMemoryUsed(); return this->Implementation->GetProcMemoryUsed();
} }
double SystemInformation::GetLoadAverage()
{
return this->Implementation->GetLoadAverage();
}
SystemInformation::LongLong SystemInformation::GetProcessId() SystemInformation::LongLong SystemInformation::GetProcessId()
{ {
return this->Implementation->GetProcessId(); return this->Implementation->GetProcessId();
...@@ -1490,6 +1502,60 @@ void SymbolProperties::Initialize(void *address) ...@@ -1490,6 +1502,60 @@ void SymbolProperties::Initialize(void *address)
} }
#endif // don't define this class if we're not using it #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 } // anonymous namespace
...@@ -3612,6 +3678,38 @@ SystemInformationImplementation::GetProcMemoryUsed() ...@@ -3612,6 +3678,38 @@ SystemInformationImplementation::GetProcMemoryUsed()
#endif #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. Get the process id of the running process.
*/ */
......
...@@ -130,6 +130,10 @@ public: ...@@ -130,6 +130,10 @@ public:
// Get system RAM used by this process id in units of KiB. // Get system RAM used by this process id in units of KiB.
LongLong GetProcMemoryUsed(); 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 // enable/disable stack trace signal handler. In order to
// produce an informative stack trace the application should // produce an informative stack trace the application should
// be dynamically linked and compiled with debug symbols. // be dynamically linked and compiled with debug symbols.
......
...@@ -452,6 +452,19 @@ int main() ...@@ -452,6 +452,19 @@ int main()
} }
#endif #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 #ifdef TEST_KWSYS_CXX_HAS_RLIMIT64
# if defined(KWSYS_HAS_LFS) # if defined(KWSYS_HAS_LFS)
# define _LARGEFILE_SOURCE # define _LARGEFILE_SOURCE
......
...@@ -87,6 +87,7 @@ int testSystemInformation(int, char*[]) ...@@ -87,6 +87,7 @@ int testSystemInformation(int, char*[])
printMethod3(info, GetProcMemoryAvailable("KWSHL","KWSPL"), "KiB"); printMethod3(info, GetProcMemoryAvailable("KWSHL","KWSPL"), "KiB");
printMethod3(info, GetHostMemoryUsed(), "KiB"); printMethod3(info, GetHostMemoryUsed(), "KiB");
printMethod3(info, GetProcMemoryUsed(), "KiB"); printMethod3(info, GetProcMemoryUsed(), "KiB");
printMethod(info, GetLoadAverage);
for (long int i = 0; i <= 31; i++) 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