From ba1e9565984047ac6d143da7af5c972369779bce Mon Sep 17 00:00:00 2001 From: SajinaKandy Date: Thu, 7 Sep 2023 09:35:40 -0700 Subject: [PATCH] Read system swappiness in omrsysinfo_get_memory_info() The code read swappiness value on Linux and sets OMRPORT_MEMINFO_NOT_AVAILABLE if the value is not available. The system wide swappiness value specified at /proc/sys/vm/swappiness for vm.swappiness is read. Closes: #5237 Signed-off-by: SajinaKandy --- fvtest/porttest/si.cpp | 3 +++ include_core/omrport.h | 5 +++++ include_core/omrporterror.h | 2 ++ port/common/omrport.tdf | 4 ++++ port/unix/omrsysinfo.c | 33 +++++++++++++++++++++++++++++++++ port/unix_include/omrcgroup.h | 1 + port/win32/omrsysinfo.c | 1 + 7 files changed, 49 insertions(+) diff --git a/fvtest/porttest/si.cpp b/fvtest/porttest/si.cpp index 8dbb91b2e7b..c6408c7df92 100644 --- a/fvtest/porttest/si.cpp +++ b/fvtest/porttest/si.cpp @@ -1299,6 +1299,9 @@ TEST(PortSysinfoTest, sysinfo_testMemoryInfo) #else /* defined (OSX) */ || (OMRPORT_MEMINFO_NOT_AVAILABLE == memInfo.cached) #endif /* defined(OSX) */ +#if defined (LINUX) + || (OMRPORT_MEMINFO_NOT_AVAILABLE == memInfo.swappiness) +#endif /* defined(LINUX) */ ) { /* Fail pltest if one of these memory usage parameters were found inconsistent. */ diff --git a/include_core/omrport.h b/include_core/omrport.h index 46348b17aa7..b97b4c9d54e 100644 --- a/include_core/omrport.h +++ b/include_core/omrport.h @@ -748,6 +748,11 @@ typedef struct J9MemoryInfo { * When not in a cgroup, this will be identical to 'buffered' field above. */ uint64_t hostBuffered; + /* The default setting for this kernel parameter of swappiness is 60. Value of 0 disables swap. + * Lower swappiness values would keep more pages in memory instead of putting them in swap space. + * Higher values will provide more I/O cache and lower values will wait longer to swap out idle application. + */ + uint64_t swappiness; } J9MemoryInfo; #define OMRPORT_MEMINFO_NOT_AVAILABLE ((uint64_t) -1) diff --git a/include_core/omrporterror.h b/include_core/omrporterror.h index 406c5e9a866..feeeee5ba06 100644 --- a/include_core/omrporterror.h +++ b/include_core/omrporterror.h @@ -418,6 +418,8 @@ #define OMRPORT_ERROR_SYSINFO_CGROUP_VERSION_NOT_AVAILABLE (OMRPORT_ERROR_SYSINFO_BASE-28) #define OMRPORT_ERROR_SYSINFO_CGROUP_FILENAME_INVALID (OMRPORT_ERROR_SYSINFO_BASE-29) #define OMRPORT_ERROR_SYSINFO_CGROUP_NULL_PARAM (OMRPORT_ERROR_SYSINFO_BASE-30) +#define OMRPORT_ERROR_SYSINFO_ERROR_SWAPPINESS_OPEN_FAILED (OMRPORT_ERROR_SYSINFO_BASE-31) +#define OMRPORT_ERROR_SYSINFO_ERROR_READING_SWAPPINESS (OMRPORT_ERROR_SYSINFO_BASE-32) /** * @name Port library initialization return codes diff --git a/port/common/omrport.tdf b/port/common/omrport.tdf index 1093e3774af..c0d49788e0d 100644 --- a/port/common/omrport.tdf +++ b/port/common/omrport.tdf @@ -1626,3 +1626,7 @@ TraceExit-Exception=Trc_PRT_mmap_map_file_unix_filestatfailed_exit Group=mmap Ov TraceExit-Exception=Trc_PRT_mmap_map_file_cannotallocatehandle_exit Group=mmap Overhead=1 Level=1 NoEnv Template="omrmmap_map_file: Could not allocate memory for handle" TraceEvent=Trc_PRT_sl_open_shared_library_noload Group=sl Overhead=1 Level=3 NoEnv Template="omrsl_open_shared_library tests if a library is already loaded, returns handle=%p" + +TraceException=Trc_PRT_retrieveLinuxMemoryStats_failedOpeningSwappinessFs Group=sysinfo Overhead=1 Level=1 NoEnv Template="retrieveLinuxMemoryStats: Failed to open /proc/sys/vm/swappiness. Error code = %d." +TraceException=Trc_PRT_retrieveLinuxMemoryStats_failedReadingSwappiness Group=sysinfo Overhead=1 Level=1 NoEnv Template="retrieveLinuxMemoryStats: Failed to read /proc/sys/vm/swappiness. Error code = %d." +TraceException=Trc_PRT_retrieveLinuxMemoryStats_unexpectedSwappinessFormat Group=sysinfo Overhead=1 Level=1 NoEnv Template="retrieveLinuxMemoryStats: Expected %d items to read, but read %d items." diff --git a/port/unix/omrsysinfo.c b/port/unix/omrsysinfo.c index cde5051fad6..a72b7ce032d 100644 --- a/port/unix/omrsysinfo.c +++ b/port/unix/omrsysinfo.c @@ -398,6 +398,7 @@ struct { /* Cgroup v1 and v2 memory files */ #define CGROUP_MEMORY_STAT_FILE "memory.stat" +#define CGROUP_MEMORY_SWAPPINESS "memory.swappiness" /* Cgroup v1 memory files */ #define CGROUP_MEMORY_LIMIT_IN_BYTES_FILE "memory.limit_in_bytes" @@ -3257,6 +3258,8 @@ omrsysinfo_get_number_CPUs_by_type(struct OMRPortLibrary *portLibrary, uintptr_t #define BUFFERS_PREFIX "Buffers:" #define BUFFERS_PREFIX_SZ (sizeof(BUFFERS_PREFIX) - 1) +#define PROC_SYS_VM_SWAPPINESS "/proc/sys/vm/swappiness" + /** * Function collects memory usage statistics by reading /proc/meminfo on Linux platforms. * @@ -3269,7 +3272,9 @@ static int32_t retrieveLinuxMemoryStatsFromProcFS(struct OMRPortLibrary *portLibrary, struct J9MemoryInfo *memInfo) { int32_t rc = 0; + int32_t rcSwappiness = 0; FILE *memStatFs = NULL; + FILE *swappinessFs = NULL; char lineString[MAX_LINE_LENGTH] = {0}; /* Open the memstat file on Linux for reading; this is readonly. */ @@ -3380,6 +3385,24 @@ retrieveLinuxMemoryStatsFromProcFS(struct OMRPortLibrary *portLibrary, struct J9 } /* end if else-if */ } /* end while() */ + swappinessFs = fopen(PROC_SYS_VM_SWAPPINESS, "r"); + if (NULL == swappinessFs) { + Trc_PRT_retrieveLinuxMemoryStats_failedOpeningSwappinessFs(errno); + rc = OMRPORT_ERROR_SYSINFO_ERROR_SWAPPINESS_OPEN_FAILED; + goto _cleanup; + } + + rcSwappiness = fscanf(swappinessFs, "%" SCNu64, &memInfo->swappiness); + if (1 != rcSwappiness) { + if (EOF == rcSwappiness) { + Trc_PRT_retrieveLinuxMemoryStats_failedReadingSwappiness(errno); + } else { + Trc_PRT_retrieveLinuxMemoryStats_unexpectedSwappinessFormat(1, rcSwappiness); + } + rc = OMRPORT_ERROR_SYSINFO_ERROR_READING_SWAPPINESS; + goto _cleanup; + } + /* Set hostXXX fields with memory stats from proc fs. * These may be used for calculating available physical memory on the host. */ @@ -3391,6 +3414,9 @@ retrieveLinuxMemoryStatsFromProcFS(struct OMRPortLibrary *portLibrary, struct J9 if (NULL != memStatFs) { fclose(memStatFs); } + if (NULL != swappinessFs) { + fclose(swappinessFs); + } return rc; } @@ -3482,6 +3508,11 @@ retrieveLinuxCgroupMemoryStats(struct OMRPortLibrary *portLibrary, struct OMRCgr cgroupMemInfo->memoryAndSwapUsage += cgroupMemInfo->memoryUsage; } + rc = readCgroupSubsystemFile(portLibrary, OMR_CGROUP_SUBSYSTEM_MEMORY, CGROUP_MEMORY_SWAPPINESS, numItemsToRead, "%" SCNu64, &cgroupMemInfo->swappiness); + if (0 != rc) { + goto _exit; + } + /* Read value of page cache memory from memory.stat file */ rc = getHandleOfCgroupSubsystemFile(portLibrary, OMR_CGROUP_SUBSYSTEM_MEMORY, CGROUP_MEMORY_STAT_FILE, &memStatFs); if (0 != rc) { @@ -3607,6 +3638,7 @@ retrieveLinuxMemoryStats(struct OMRPortLibrary *portLibrary, struct J9MemoryInfo } } + memInfo->swappiness = cgroupMemInfo.swappiness; memInfo->cached = cgroupMemInfo.cached; /* Buffered value is not available when running in a cgroup. * See https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt @@ -3771,6 +3803,7 @@ omrsysinfo_get_memory_info(struct OMRPortLibrary *portLibrary, struct J9MemoryIn memInfo->availSwap = OMRPORT_MEMINFO_NOT_AVAILABLE; memInfo->cached = OMRPORT_MEMINFO_NOT_AVAILABLE; memInfo->buffered = OMRPORT_MEMINFO_NOT_AVAILABLE; + memInfo->swappiness = OMRPORT_MEMINFO_NOT_AVAILABLE; memInfo->hostAvailPhysical = OMRPORT_MEMINFO_NOT_AVAILABLE; memInfo->hostCached = OMRPORT_MEMINFO_NOT_AVAILABLE; diff --git a/port/unix_include/omrcgroup.h b/port/unix_include/omrcgroup.h index 54511487496..73ad15e7942 100644 --- a/port/unix_include/omrcgroup.h +++ b/port/unix_include/omrcgroup.h @@ -36,6 +36,7 @@ typedef struct OMRCgroupMemoryInfo { uint64_t memoryUsage; /**< current memory usage in bytes (as in memory.usage_in_bytes file)*/ uint64_t memoryAndSwapLimit; /**< memory + swap limit in bytes (as in memory.memsw.limit_in_bytes file)*/ uint64_t memoryAndSwapUsage; /**< current memory + swap usage in bytes (as in memory.memsw.usage_in_bytes file) */ + uint64_t swappiness; /**< indicates kernel aggressiveness (0-100) in swapping memory pages for cgroups, and is not supported on cgroups V2 */ uint64_t cached; /**< page cache memory (as in memory.stat file)*/ } OMRCgroupMemoryInfo; diff --git a/port/win32/omrsysinfo.c b/port/win32/omrsysinfo.c index 2a7b7b8bc84..fd81f8730f9 100644 --- a/port/win32/omrsysinfo.c +++ b/port/win32/omrsysinfo.c @@ -901,6 +901,7 @@ omrsysinfo_get_memory_info(struct OMRPortLibrary *portLibrary, struct J9MemoryIn memInfo->availSwap = OMRPORT_MEMINFO_NOT_AVAILABLE; memInfo->cached = OMRPORT_MEMINFO_NOT_AVAILABLE; memInfo->buffered = OMRPORT_MEMINFO_NOT_AVAILABLE; + memInfo->swappiness = OMRPORT_MEMINFO_NOT_AVAILABLE; aMemStatusEx.dwLength = sizeof(aMemStatusEx); rc = GlobalMemoryStatusEx(&aMemStatusEx);