[ZBX-9619] The value of the available swap of Windows is illegal. Created: 2015 Jun 05  Updated: 2017 May 30  Resolved: 2016 Oct 11

Status: Closed
Project: ZABBIX BUGS AND ISSUES
Component/s: Agent (G)
Affects Version/s: 2.4.1
Fix Version/s: None

Type: Incident report Priority: Blocker
Reporter: Kazuo Ito Assignee: Unassigned
Resolution: Won't fix Votes: 2
Labels: memory, windows
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Windows Server 2012 R2,Zabbix2.4.1


Attachments: File memstat.exe    

 Description   

Zabbix2.2.9 are normally acquired.
Zabbix2.4.1 the calculation has been changed.

?Zabbix2.2.9

	if (NULL != zbx_GlobalMemoryStatusEx)
	{
		ms_ex.dwLength = sizeof(MEMORYSTATUSEX);

		zbx_GlobalMemoryStatusEx(&ms_ex);

		if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total"))
			SET_UI64_RESULT(result, ms_ex.ullTotalPageFile);
		else if (0 == strcmp(mode, "free"))
			SET_UI64_RESULT(result, ms_ex.ullAvailPageFile);
		else if (0 == strcmp(mode, "used"))
			SET_UI64_RESULT(result, ms_ex.ullTotalPageFile - ms_ex.ullAvailPageFile);
		else
			return SYSINFO_RET_FAIL;
	}
	else
	{
		GlobalMemoryStatus(&ms);

		if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total"))
			SET_UI64_RESULT(result, ms.dwTotalPageFile);
		else if (0 == strcmp(mode, "free"))
			SET_UI64_RESULT(result, ms.dwAvailPageFile);
		else if (0 == strcmp(mode, "used"))
			SET_UI64_RESULT(result, ms.dwTotalPageFile - ms.dwAvailPageFile);
		else
			return SYSINFO_RET_FAIL;
	}

?Zabbix2.4.1

	if (NULL != zbx_GlobalMemoryStatusEx)
	{
		ms_ex.dwLength = sizeof(MEMORYSTATUSEX);

		zbx_GlobalMemoryStatusEx(&ms_ex);

		real_swap_total = ms_ex.ullTotalPageFile > ms_ex.ullTotalPhys ?
				ms_ex.ullTotalPageFile - ms_ex.ullTotalPhys : 0;
		real_swap_avail = ms_ex.ullAvailPageFile > ms_ex.ullAvailPhys ?
				ms_ex.ullAvailPageFile - ms_ex.ullAvailPhys : 0;
	}
	else
	{
		GlobalMemoryStatus(&ms);

		real_swap_total = ms.dwTotalPageFile > ms.dwTotalPhys ?
				ms.dwTotalPageFile - ms.dwTotalPhys : 0;
		real_swap_avail = ms.dwAvailPageFile > ms.dwAvailPhys ?
				ms.dwAvailPageFile - ms.dwAvailPhys : 0;
	}

	if (real_swap_avail > real_swap_total)
		real_swap_avail = real_swap_total;

	if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total"))
		SET_UI64_RESULT(result, real_swap_total);
	else if (0 == strcmp(mode, "free"))
		SET_UI64_RESULT(result, real_swap_avail);
	else if (0 == strcmp(mode, "pfree"))
		SET_DBL_RESULT(result, (real_swap_avail / (double)real_swap_total) * 100.0);
	else if (0 == strcmp(mode, "used"))
		SET_UI64_RESULT(result, real_swap_total - real_swap_avail);
	else
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
		return SYSINFO_RET_FAIL;
	}


 Comments   
Comment by Aleksandrs Saveljevs [ 2015 Jun 08 ]

The changes to swap calculation on Windows were done under ZBXNEXT-2225. That task introduced the following comment into src/libs/zbxsysinfo/win32/swap.c, which explains the reason behind new calculations:

/***************************************************************************
 *                                                                         *
 * Due to the way Windows API functions report memory metrics,             *
 * it is impossible to accurately retrieve swap (virtual memory)           *
 * sizes as Windows reports the total commit memory which is physical      *
 * memory plus swap file sizes. The only resolution that could be applied  *
 * was calculatively deducting the swap sizes knowing the page and         *
 * physical memory sizes.                                                  *
 *                                                                         *
 * While developing this solution, it was found that sometimes (in         *
 * virtualized environments or when page file is disabled) the calculated  *
 * swap values are outside of possible bounds. For example, the available  *
 * swap size may appear to be larger than the total swap memory size of    *
 * the system, or even the calculated swap sizes may result in negative    *
 * values (in system with disabled page file).                             *
 *                                                                         *
 * Taking these fallacious conditions into account, these calculations     *
 * guarantee that the available swap size is never larger than the total   *
 * available (if it is reported as such, it is lowered to the total        *
 * as there is a higher probability of that number staying consistent      *
 * than the other way around). In case of swap size calculations resulting *
 * in negative values, the corresponding values are set to 0.              *
 *                                                                         *
 * As the result the returned values might not be exactly accurate         *
 * depending on the system and environment, but they ought to be close     *
 * enough.                                                                 *
 *                                                                         *
 * NB: The reason why GlobalMemoryStatus[Ex] are used is their             *
 * availability on Windows 2000 and later, as opposed to other functions   *
 * of a similar nature (like GetPerformanceInfo) that are not supported    *
 * on some versions of Windows.                                            *
 *                                                                         *
 ***************************************************************************/

The issue description only says that old calculations are correct and that new calculations are wrong, but does not describe what is wrong exactly. Could you please elaborate more on the problem?

Comment by Kazuo Ito [ 2015 Jun 08 ]

Zabbix was get 0 of value from 'system.swap.size[,free]'.

The value was confirmed by Windows server 2012 R2.
Sorry in Japanese.

ページングファイル:2,432MB       <- paging file

物理メモリの合計:16,376 MB       <- physical memory
利用できる物理メモリ:14,947 MB   <- available physical memory
仮想メモリ:最大サイズ:18,808 MB <- virtual memory max
仮想メモリ:利用可能:13,195 MB   <- available virtual memory
仮想メモリ:使用中:5,613 MB      <- used virtual memory

Correct 'system.swap.size[,free]' is value of 13,195 MB.

Please put out the value of the ullAvailVirtual in 'system.swap.size[,free]' .

Memory Performance Information
Virtual Bytes = MEMORYSTATUSEX.ullTotalVirtual – MEMORYSTATUSEX.ullAvailVirtual

Comment by Kim Jongkwon [ 2016 Oct 04 ]

This is still happening on zabbix 3.2.0.

I suppose to that calculation was wrong from the source - "real_swap_avail"
I think this returns 0 instead of value problem happen causing "Virtual Memory: Available <= Available Physical Memory"

Please consider to fix and checking this cases.

I confirm this problem with Windows 10 / Zabbix Agent (Win) 3.2.0

  • Problem case (value : 0):
    c:\Program Files\Zabbix Agent>systeminfo | find "Memory"
    Total Physical Memory:     3,981 MB
    Available Physical Memory: 1,752 MB
    Virtual Memory: Max Size:  4,493 MB
    Virtual Memory: Available: 1,524 MB
    Virtual Memory: In Use:    2,969 MB
    
c:\Program Files\Zabbix Agent>zabbix_agentd -t system.swap.size[,free]
system.swap.size[,free]                       [u|0]
  • Value returns case (But I'm not sure, 430MB is that correct value?) :
    c:\Program Files\Zabbix Agent>systeminfo | find "Memory"
    Total Physical Memory:     3,981 MB
    Available Physical Memory: 2,292 MB
    Virtual Memory: Max Size:  5,517 MB
    Virtual Memory: Available: 2,716 MB
    Virtual Memory: In Use:    2,801 MB
    
c:\Program Files\Zabbix Agent>zabbix_agentd -t system.swap.size[,free]
system.swap.size[,free]                       [u|451350528]
Comment by Andris Zeila [ 2016 Oct 05 ]

A question - were the systems (with system.swap.size[,free] returning 0) running in virtualized environments? When I was investigating the swap size calculations I was getting strange results when testing on virtualbox.

Regarding the logic of calculations - virtual memory is total memory available on system. This includes both - physical memory and page file (swap). Therefore reporting swap size based on purely virtual memory statistics is wrong. We either should find the real swap file usage, or rename the key from system.swap.size to system.vmem.size or similar on windows.

Based on that the 430MB free swap size in the last example seems about right: Virtual Memory: Available - Available Physical Memory = Available Page File (~430MB).

The problem with 0 swap size could be because the statistics returned by GlobalMemoryStatus are:

for the system or the current process, whichever is smaller, in bytes

It would be better to use GetPerformanceInfo(), but we would have to leave current code for Windows 2000 (we can't drop win2k support in older versions). The safest way might be to use Paging File, %pagefile in use, _Total performance counter.

Comment by Kim Jongkwon [ 2016 Oct 05 ]

Andris, Thank you for checking and giving me a very useful informations

The answer to the question - This is NOT virtualized environments.
I was testing with my own Windows10 Home(64bit) OS.

Comment by Andris Zeila [ 2016 Oct 05 ]

Would it be possible to run the attached memstat.exe on some problematic systems?

Comment by Kim Jongkwon [ 2016 Oct 06 ]

Problem with 0 value - memstat.exe on Win10 PC results below :

> memstat
Used memory statistics:
        GlobalMemoryStatusEx():
                commit: 4340684 / 5595348
                phys  : 2710880 / 4076980
                swap  : 1629804 / 1518368 (107.34%)
        GetPerformanceInfo():
                commit:  146380 / 1401044
                phys  : 2710884 / 4076980
                cache : 1049316
                swap  : 1629800 / 1518368 (107.34%)
        QueryPerformanceCounter():
                swap bytes: 3201122304
                swap %    : 9.77%

> zabbix_agentd -t system.swap.size[,free]
system.swap.size[,free]                       [u|0]

> systeminfo | find "Memory"
Total Physical Memory:     3,981 MB
Available Physical Memory: 1,328 MB
Virtual Memory: Max Size:  5,464 MB
Virtual Memory: Available: 1,222 MB
Virtual Memory: In Use:    4,242 MB
Comment by Andris Zeila [ 2016 Oct 06 ]

According to systeminfo there are 2.653 MB used physical memory and 4.242 MB used total memory (physical + swap). So that would mean 1.589 MB of swap used (which appears to be more than total swap size, but there might be some internal allocations Microsfoft is not including or something). So Zabbix reporting 0 free swap size seems to be about right.

Changing system.swap.size to report virtual memory status on windows seems semantically wrong - I'd suggest adding a new Windows key that would mirror virtual memory statistics reported by Windows API.

See ZBXNEXT-3487

Comment by Kim Jongkwon [ 2016 Oct 06 ]

I agree with your opinion.
And I think should document to add some of the details mention in system.swap.size key for windows, after ZBXNEXT-3487.

Thank you,

Generated at Thu Apr 25 05:15:06 EEST 2024 using Jira 9.12.4#9120004-sha1:625303b708afdb767e17cb2838290c41888e9ff0.