in source/code/scxsystemlib/memory/memoryinstance.cpp [812:1120]
void MemoryInstance::Update()
{
SCX_LOGTRACE(m_log, L"MemoryInstance Update()");
#if defined(linux)
/**
Update the object members with values from /proc/meminfo.
\ex
/proc/meminfo:
MemTotal: 516400 kB
MemFree: 91988 kB
Buffers: 46148 kB
Cached: 277860 kB
SwapCached: 64136 kB
Active: 299804 kB
Inactive: 97372 kB
HighTotal: 0 kB
HighFree: 0 kB
LowTotal: 516400 kB
LowFree: 91988 kB
SwapTotal: 514040 kB
SwapFree: 402508 kB
Dirty: 676 kB
Writeback: 0 kB
Mapped: 96832 kB
Slab: 20356 kB
CommitLimit: 772240 kB
Committed_AS: 281692 kB
PageTables: 1700 kB
VmallocTotal: 507896 kB
VmallocUsed: 3228 kB
VmallocChunk: 504576 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
Hugepagesize: 4096 kB
We are interested in the following fields:
MemTotal
MemFree
SwapTotal
SwapFree
*/
/**
The 3.14+ linux kernel has MemAvailable: which gives more appropirate value for available memory. We will be getting the available memory from MemAvailable: (if present) instead of MemFree + Buffers + Cached
MemTotal: 3522864 kB
MemFree: 175844 kB
MemAvailable: 2813432 kB
Buffers: 36 kB
Cached: 289148 kB
SwapCached: 332 kB
Active: 234424 kB
Inactive: 250828 kB
Active(anon): 94120 kB
Inactive(anon): 203372 kB
Active(file): 140304 kB
Inactive(file): 47456 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 6655996 kB
SwapFree: 6638924 kB
Dirty: 8 kB
Writeback: 0 kB
AnonPages: 195772 kB
Mapped: 28868 kB
Shmem: 101424 kB
Slab: 2765564 kB
SReclaimable: 2745856 kB
SUnreclaim: 19708 kB
KernelStack: 4224 kB
PageTables: 6588 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 8417428 kB
Committed_AS: 1004816 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 67624 kB
VmallocChunk: 34359663604 kB
HardwareCorrupted: 0 kB
AnonHugePages: 75776 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 94144 kB
DirectMap2M: 3575808 kB
*/
std::vector<std::wstring> lines = m_deps->GetMemInfoLines();
scxulong buffers = 0, cached = 0, reportedAvailableMemory = 0; // KB
for (size_t i = 0; i < lines.size(); i++)
{
std::wstring line = lines[i];
SCX_LOGHYSTERICAL(m_log, std::wstring(L"UpdateFromMemInfo() - Read line: ").append(line));
std::vector<std::wstring> tokens;
StrTokenize(line, tokens);
if (tokens.size() >= 2)
{
if (L"MemTotal:" == tokens[0])
{
try
{
m_totalPhysicalMemory = StrToULong(tokens[1]) * 1024; // Resulting units: bytes
m_foundTotalPhysMem = true;
SCX_LOGHYSTERICAL(m_log, StrAppend(L" totalPhysicalMemory = ", m_totalPhysicalMemory));
}
catch (const SCXNotSupportedException& e)
{
SCX_LOGWARNING(m_log, std::wstring(L"Could not read m_totalPhysicalMemory from :").append(line).append(L" - ").append(e.What()));
}
}
if (L"MemAvailable:" == tokens[0])
{
try
{
reportedAvailableMemory = StrToULong(tokens[1]) * 1024; // Resulting units: bytes
m_foundAvailMem = true;
SCX_LOGHYSTERICAL(m_log, StrAppend(L" availableMemory = ", m_availableMemory));
}
catch (const SCXNotSupportedException& e)
{
SCX_LOGWARNING(m_log, std::wstring(L"Could not read m_availableMemory from: ").append(line).append(L" - ").append(e.What()));
}
}
if (L"MemFree:" == tokens[0])
{
try
{
m_availableMemory = StrToULong(tokens[1]) * 1024; // Resulting units: bytes
m_foundAvailMem = true;
SCX_LOGHYSTERICAL(m_log, StrAppend(L" availableMemory = ", m_availableMemory));
}
catch (const SCXNotSupportedException& e)
{
SCX_LOGWARNING(m_log, std::wstring(L"Could not read m_availableMemory from: ").append(line).append(L" - ").append(e.What()));
}
}
if (L"Buffers:" == tokens[0])
{
try
{
buffers = StrToULong(tokens[1]) * 1024; // Resulting units: bytes
SCX_LOGHYSTERICAL(m_log, StrAppend(L" buffers = ", buffers));
}
catch (const SCXNotSupportedException& e)
{
SCX_LOGWARNING(m_log, std::wstring(L"Could not read buffers from: ").append(line).append(L" - ").append(e.What()));
}
}
if (L"Cached:" == tokens[0])
{
try
{
cached = StrToULong(tokens[1]) * 1024; // Resulting units: bytes
SCX_LOGHYSTERICAL(m_log, StrAppend(L" Cached = ", cached));
}
catch (const SCXNotSupportedException& e)
{
SCX_LOGWARNING(m_log, std::wstring(L"Could not read buffers from: ").append(line).append(L" - ").append(e.What()));
}
}
if (L"SwapTotal:" == tokens[0])
{
try
{
m_totalSwap = StrToULong(tokens[1]) * 1024; // Resulting units: bytes
m_foundTotalSwap = true;
SCX_LOGHYSTERICAL(m_log, StrAppend(L" totalSwap = ", m_totalSwap));
}
catch (const SCXNotSupportedException& e)
{
SCX_LOGWARNING(m_log, std::wstring(L"Could not read m_totalSwap from: ").append(line).append(L" - ").append(e.What()));
}
}
if (L"SwapFree:" == tokens[0])
{
try
{
m_availableSwap = StrToULong(tokens[1]) * 1024; // Resulting units: bytes
m_foundAvailSwap = true;
SCX_LOGHYSTERICAL(m_log, StrAppend(L" availableSwap = ", m_availableSwap));
}
catch (const SCXNotSupportedException& e)
{
SCX_LOGWARNING(m_log, std::wstring(L"Could not read m_availableSwap from: ").append(line).append(L" - ").append(e.What()));
}
}
}
}
// perform some adjustments and calculations. Resulting units: bytes.
if (reportedAvailableMemory)
{
m_availableMemory = reportedAvailableMemory;
} else {
m_availableMemory += buffers + cached;
}
m_usedMemory = m_totalPhysicalMemory - m_availableMemory;
m_usedSwap = m_totalSwap - m_availableSwap;
// This is "weak" in that it can easily be missed; we verify this in unit tests too now
SCXASSERT(m_foundTotalPhysMem && "MemTotal not found");
SCXASSERT(m_foundAvailMem && "MemFree not found");
SCXASSERT(m_foundTotalSwap && "SwapTotal not found");
SCXASSERT(m_foundAvailSwap && "SwapFree not found");
#elif defined(sun)
/*
Update the object members with info from sysconf and swapctl.
*/
scxulong pageSize = m_deps->GetPageSize();
m_totalPhysicalMemory = m_deps->GetPhysicalPages() * pageSize; // Resulting units: bytes
m_availableMemory = m_deps->GetAvailablePhysicalPages() * pageSize; // Resulting units: bytes
SCX_LOGTRACE(m_log, StrAppend(L"MemoryInstance::Update() - Page Size (", pageSize).append(L")"));
SCX_LOGTRACE(m_log, StrAppend(L"MemoryInstance::Update() - Total Physical Memory (", m_totalPhysicalMemory).append(L")"));
SCX_LOGTRACE(m_log, StrAppend(L"MemoryInstance::Update() - Memory Available (", m_availableMemory).append(L")"));
scxulong cacheSize = 0;
GetCacheSize(cacheSize);
SCX_LOGTRACE(m_log, StrAppend(L"MemoryInstance::Update() - ZFS Cache Size (", cacheSize).append(L")"));
m_availableMemory += cacheSize;
m_usedMemory = m_totalPhysicalMemory - m_availableMemory; // Resulting units: bytes
SCX_LOGTRACE(m_log, StrAppend(L"MemoryInstance::Update() - New Memory Available (", m_availableMemory).append(L")"));
SCX_LOGTRACE(m_log, StrAppend(L"MemoryInstance::Update() - Used Memory (", m_usedMemory).append(L")"));
scxulong max_pages = 0;
scxulong reserved_pages = 0;
m_deps->GetSwapInfo(max_pages, reserved_pages);
SCX_LOGTRACE(m_log, StrAppend(L"MemoryInstance::Update() - Swap Max Pages (", max_pages).append(L")"));
SCX_LOGTRACE(m_log, StrAppend(L"MemoryInstance::Update() - Swap Reserved Pages (", reserved_pages).append(L")"));
m_totalSwap = max_pages * pageSize; // Resulting units: bytes
m_availableSwap = (max_pages - reserved_pages) * pageSize; // Resulting units: bytes
m_usedSwap = reserved_pages * pageSize; // Resulting units: bytes
SCX_LOGTRACE(m_log, StrAppend(L"MemoryInstance::Update() - Swap Total (", m_totalSwap).append(L")"));
SCX_LOGTRACE(m_log, StrAppend(L"MemoryInstance::Update() - Swap Available (", m_availableSwap).append(L")"));
SCX_LOGTRACE(m_log, StrAppend(L"MemoryInstance::Update() - Swap Used (", m_usedSwap).append(L")"));
#elif defined(hpux)
scxulong page_size = 0;
scxulong physical_memory = 0;
scxulong real_pages = 0;
scxulong free_pages = 0;
m_deps->GetStaticMemoryInfo(page_size, physical_memory);
m_deps->GetDynamicMemoryInfo(real_pages, free_pages);
m_totalPhysicalMemory = (physical_memory * page_size); // Resulting units: bytes
m_usedMemory = (real_pages * page_size); // Resulting units: bytes
m_availableMemory = (free_pages * page_size); // Resulting units: bytes
// The reservedMemory size varies with a few MB up and down, so it's best to recompute
// this number every time so that the used and free percentages adds up.
m_reservedMemory = m_totalPhysicalMemory - m_usedMemory - m_availableMemory;
scxulong max_pages = 0;
scxulong reserved_pages = 0;
m_deps->GetSwapInfo(max_pages, reserved_pages);
// totalSwap is the total size of all external swap devices plus swap memory, if enabled
// availableSwap is the size of remaining device swap (with reserved memory subtracted)
// plus remaining swap memory, if that was enabled in system configuration.
// usedSwap is the difference between those. This is consistent with the 'total'
// numbers when you do 'swapinfo -t'.
m_totalSwap = max_pages * page_size; // Resulting units: bytes
m_availableSwap = reserved_pages * page_size; // Resulting units: bytes
m_usedSwap = m_totalSwap - m_availableSwap; // Resulting units: bytes
#elif defined(aix)
scxulong total_pages = 0;
scxulong free_pages = 0;
scxulong max_swap_pages = 0;
scxulong free_swap_pages = 0;
m_deps->GetMemInfo(total_pages, free_pages, max_swap_pages, free_swap_pages);
// All memory data given in bytes
m_totalPhysicalMemory = (total_pages * 4) * 1024; // Resulting units: bytes
m_availableMemory = (free_pages * 4) * 1024; // Resulting units: bytes
m_usedMemory = m_totalPhysicalMemory - m_availableMemory; // Resulting units: bytes
m_totalSwap = (max_swap_pages * 4) * 1024; // Resulting units: bytes
m_availableSwap = (free_swap_pages * 4) * 1024; // Resulting units: bytes
m_usedSwap = m_totalSwap - m_availableSwap;
#else
#error "Not implemented for this platform."
#endif
}