1// +build windows 2 3package mem 4 5import ( 6 "context" 7 "unsafe" 8 9 "github.com/shirou/gopsutil/v3/internal/common" 10 "golang.org/x/sys/windows" 11) 12 13var ( 14 procGlobalMemoryStatusEx = common.Modkernel32.NewProc("GlobalMemoryStatusEx") 15 procGetPerformanceInfo = common.ModPsapi.NewProc("GetPerformanceInfo") 16) 17 18type memoryStatusEx struct { 19 cbSize uint32 20 dwMemoryLoad uint32 21 ullTotalPhys uint64 // in bytes 22 ullAvailPhys uint64 23 ullTotalPageFile uint64 24 ullAvailPageFile uint64 25 ullTotalVirtual uint64 26 ullAvailVirtual uint64 27 ullAvailExtendedVirtual uint64 28} 29 30func VirtualMemory() (*VirtualMemoryStat, error) { 31 return VirtualMemoryWithContext(context.Background()) 32} 33 34func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { 35 var memInfo memoryStatusEx 36 memInfo.cbSize = uint32(unsafe.Sizeof(memInfo)) 37 mem, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memInfo))) 38 if mem == 0 { 39 return nil, windows.GetLastError() 40 } 41 42 ret := &VirtualMemoryStat{ 43 Total: memInfo.ullTotalPhys, 44 Available: memInfo.ullAvailPhys, 45 Free: memInfo.ullAvailPhys, 46 UsedPercent: float64(memInfo.dwMemoryLoad), 47 } 48 49 ret.Used = ret.Total - ret.Available 50 return ret, nil 51} 52 53type performanceInformation struct { 54 cb uint32 55 commitTotal uint64 56 commitLimit uint64 57 commitPeak uint64 58 physicalTotal uint64 59 physicalAvailable uint64 60 systemCache uint64 61 kernelTotal uint64 62 kernelPaged uint64 63 kernelNonpaged uint64 64 pageSize uint64 65 handleCount uint32 66 processCount uint32 67 threadCount uint32 68} 69 70func SwapMemory() (*SwapMemoryStat, error) { 71 return SwapMemoryWithContext(context.Background()) 72} 73 74func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) { 75 var perfInfo performanceInformation 76 perfInfo.cb = uint32(unsafe.Sizeof(perfInfo)) 77 mem, _, _ := procGetPerformanceInfo.Call(uintptr(unsafe.Pointer(&perfInfo)), uintptr(perfInfo.cb)) 78 if mem == 0 { 79 return nil, windows.GetLastError() 80 } 81 tot := perfInfo.commitLimit * perfInfo.pageSize 82 used := perfInfo.commitTotal * perfInfo.pageSize 83 free := tot - used 84 var usedPercent float64 85 if tot == 0 { 86 usedPercent = 0 87 } else { 88 usedPercent = float64(used) / float64(tot) * 100 89 } 90 ret := &SwapMemoryStat{ 91 Total: tot, 92 Used: used, 93 Free: free, 94 UsedPercent: usedPercent, 95 } 96 97 return ret, nil 98} 99