1
2
3
4
5 package oshi.hardware.platform.windows;
6
7 import static oshi.util.Memoizer.defaultExpiration;
8 import static oshi.util.Memoizer.memoize;
9
10 import java.util.Map;
11 import java.util.function.Supplier;
12
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
15
16 import com.sun.jna.platform.win32.Kernel32;
17 import com.sun.jna.platform.win32.Psapi;
18
19 import oshi.annotation.concurrent.ThreadSafe;
20 import oshi.driver.windows.perfmon.MemoryInformation;
21 import oshi.driver.windows.perfmon.MemoryInformation.PageSwapProperty;
22 import oshi.driver.windows.perfmon.PagingFile;
23 import oshi.driver.windows.perfmon.PagingFile.PagingPercentProperty;
24 import oshi.hardware.common.AbstractVirtualMemory;
25 import oshi.jna.Struct.CloseablePerformanceInformation;
26 import oshi.util.tuples.Pair;
27 import oshi.util.tuples.Triplet;
28
29
30
31
32 @ThreadSafe
33 final class WindowsVirtualMemory extends AbstractVirtualMemory {
34
35 private static final Logger LOG = LoggerFactory.getLogger(WindowsVirtualMemory.class);
36
37 private final WindowsGlobalMemory global;
38
39 private final Supplier<Long> used = memoize(WindowsVirtualMemory::querySwapUsed, defaultExpiration());
40
41 private final Supplier<Triplet<Long, Long, Long>> totalVmaxVused = memoize(
42 WindowsVirtualMemory::querySwapTotalVirtMaxVirtUsed, defaultExpiration());
43
44 private final Supplier<Pair<Long, Long>> swapInOut = memoize(WindowsVirtualMemory::queryPageSwaps,
45 defaultExpiration());
46
47
48
49
50
51
52 WindowsVirtualMemory(WindowsGlobalMemory windowsGlobalMemory) {
53 this.global = windowsGlobalMemory;
54 }
55
56 @Override
57 public long getSwapUsed() {
58 return this.global.getPageSize() * used.get();
59 }
60
61 @Override
62 public long getSwapTotal() {
63 return this.global.getPageSize() * totalVmaxVused.get().getA();
64 }
65
66 @Override
67 public long getVirtualMax() {
68 return this.global.getPageSize() * totalVmaxVused.get().getB();
69 }
70
71 @Override
72 public long getVirtualInUse() {
73 return this.global.getPageSize() * totalVmaxVused.get().getC();
74 }
75
76 @Override
77 public long getSwapPagesIn() {
78 return swapInOut.get().getA();
79 }
80
81 @Override
82 public long getSwapPagesOut() {
83 return swapInOut.get().getB();
84 }
85
86 private static long querySwapUsed() {
87 return PagingFile.querySwapUsed().getOrDefault(PagingPercentProperty.PERCENTUSAGE, 0L);
88 }
89
90 private static Triplet<Long, Long, Long> querySwapTotalVirtMaxVirtUsed() {
91 try (CloseablePerformanceInformation perfInfo = new CloseablePerformanceInformation()) {
92 if (!Psapi.INSTANCE.GetPerformanceInfo(perfInfo, perfInfo.size())) {
93 LOG.error("Failed to get Performance Info. Error code: {}", Kernel32.INSTANCE.GetLastError());
94 return new Triplet<>(0L, 0L, 0L);
95 }
96 return new Triplet<>(perfInfo.CommitLimit.longValue() - perfInfo.PhysicalTotal.longValue(),
97 perfInfo.CommitLimit.longValue(), perfInfo.CommitTotal.longValue());
98 }
99 }
100
101 private static Pair<Long, Long> queryPageSwaps() {
102 Map<PageSwapProperty, Long> valueMap = MemoryInformation.queryPageSwaps();
103 return new Pair<>(valueMap.getOrDefault(PageSwapProperty.PAGESINPUTPERSEC, 0L),
104 valueMap.getOrDefault(PageSwapProperty.PAGESOUTPUTPERSEC, 0L));
105 }
106 }