Use GlobalMemoryStatusEx to get total physical memory on Windows node

This commit is contained in:
Jiangtian Li 2017-12-12 17:50:17 -08:00
parent 098cba3f14
commit 071be11db5

View File

@ -23,18 +23,32 @@ import (
"os"
"runtime"
"sync"
"syscall"
"time"
"unsafe"
"github.com/golang/glog"
cadvisorapi "github.com/google/cadvisor/info/v1"
"golang.org/x/sys/windows"
"k8s.io/apimachinery/pkg/util/wait"
)
// MemoryStatusEx is the same as Windows structure MEMORYSTATUSEX
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366770(v=vs.85).aspx
type MemoryStatusEx struct {
Length uint32
MemoryLoad uint32
TotalPhys uint64
AvailPhys uint64
TotalPageFile uint64
AvailPageFile uint64
TotalVirtual uint64
AvailVirtual uint64
AvailExtendedVirtual uint64
}
var (
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
procGetPhysicallyInstalledSystemMemory = modkernel32.NewProc("GetPhysicallyInstalledSystemMemory")
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
procGlobalMemoryStatusEx = modkernel32.NewProc("GlobalMemoryStatusEx")
)
// NewPerfCounterClient creates a client using perf counters
@ -163,20 +177,24 @@ func (p *perfCounterNodeStatsClient) convertCPUValue(cpuValue uint64) uint64 {
}
func getPhysicallyInstalledSystemMemoryBytes() (uint64, error) {
var physicalMemoryKiloBytes uint64
// We use GlobalMemoryStatusEx instead of GetPhysicallyInstalledSystemMemory
// on Windows node for the following reasons:
// 1. GetPhysicallyInstalledSystemMemory retrieves the amount of physically
// installed RAM from the computer's SMBIOS firmware tables.
// https://msdn.microsoft.com/en-us/library/windows/desktop/cc300158(v=vs.85).aspx
// On some VM, it is unable to read data from SMBIOS and fails with ERROR_INVALID_DATA.
// 2. On Linux node, total physical memory is read from MemTotal in /proc/meminfo.
// GlobalMemoryStatusEx returns the amount of physical memory that is available
// for the operating system to use. The amount returned by GlobalMemoryStatusEx
// is closer in parity with Linux
// https://www.kernel.org/doc/Documentation/filesystems/proc.txt
var statex MemoryStatusEx
statex.Length = uint32(unsafe.Sizeof(statex))
ret, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&statex)))
if ok := getPhysicallyInstalledSystemMemory(&physicalMemoryKiloBytes); !ok {
if ret == 0 {
return 0, errors.New("unable to read physical memory")
}
return physicalMemoryKiloBytes * 1024, nil // convert kilobytes to bytes
}
func getPhysicallyInstalledSystemMemory(totalMemoryInKilobytes *uint64) bool {
ret, _, _ := syscall.Syscall(procGetPhysicallyInstalledSystemMemory.Addr(), 1,
uintptr(unsafe.Pointer(totalMemoryInKilobytes)),
0,
0)
return ret != 0
return statex.TotalPhys, nil
}