diff --git a/CHANGELOG.md b/CHANGELOG.md index e34b41623b9..e3cfdfc5727 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * [#774](https://github.com/oshi/oshi/pull/774): API overhaul - ComputerSystem, Baseboard, and Firmware. - [@dbwiddis](https://github.com/dbwiddis). * [#775](https://github.com/oshi/oshi/pull/775): API overhaul - GlobalMemory, new VirtualMemory. - [@dbwiddis](https://github.com/dbwiddis). * [#776](https://github.com/oshi/oshi/pull/776): oshi-demo artifact. - [@dbwiddis](https://github.com/dbwiddis). +* [#779](https://github.com/oshi/oshi/pull/779): API overhaul - CentralProcessor, new LogicalProcessor. - [@dbwiddis](https://github.com/dbwiddis). * Your contribution here. 3.13.0 (1/18/2019) diff --git a/UPGRADING.md b/UPGRADING.md index ace06f1c128..b0ea5355c14 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -12,10 +12,6 @@ to demonstrate OSHI's capabilities and integration with other libraries. ## API Changes -There is a new `VirtualMemory `class which is accessible with a getter from -`GlobalMemory`. Methods associated with swap file usage were moved to this -new class. - Several changes in the API highlight which attributes do not change and which fetch dynamic information, as well as highlight operations with latency or expensive computations. In general the following rules are followed: @@ -29,6 +25,20 @@ available to cause the getters to return updated values. The following getX() methods are now queryX(): - TBD +There is a new `VirtualMemory `class which is accessible with a getter from +`GlobalMemory`. Methods associated with swap file usage were moved to this +new class. + +The `CentralProcessor` setters were removed from the API. The methods +`getSystemCpuLoadBetweenTicks()` and `getProcessorCpuLoadBetweenTicks()` now take +an argument with the previous set of ticks, rather than internally saving the +previous call. This enables users to measure over a longer period or multiple +different periods. The `getSystemCpuLoad()` method is now a direct passthrough +to the `OperatingSystemMXBean` method if running an Oracle JVM, otherwise it +returns a negative value. The no-argument `getSystemLoadAverage()` has been +removed; users can call with an argument of 1 to obtain the same value. + + # Guide to upgrading from OSHI 2.x to 3.x The most significant change in OSHI 3.0 is the separation of JSON output to a diff --git a/oshi-core/src/main/java/oshi/hardware/CentralProcessor.java b/oshi-core/src/main/java/oshi/hardware/CentralProcessor.java index b5a4bb2b2d8..ac2e533b5b3 100644 --- a/oshi-core/src/main/java/oshi/hardware/CentralProcessor.java +++ b/oshi-core/src/main/java/oshi/hardware/CentralProcessor.java @@ -26,73 +26,13 @@ import java.io.Serializable; /** - * The Central Processing Unit (CPU) or the processor is the portion of a - * computer system that carries out the instructions of a computer program, and - * is the primary element carrying out the computer's functions. - * - * @author dblock[at]dblock[dot]org + * This class represents the entire Central Processing Unit (CPU) of a computer + * system, which may contain one or more physical packages (sockets), one or + * more physical processors (cores), and one or more logical processors (what + * the Operating System sees, which may include hyperthreaded cores.) */ public interface CentralProcessor extends Serializable { - /** - * Index of CPU tick counters in the {@link #getSystemCpuLoadTicks()} and - * {@link #getProcessorCpuLoadTicks()} arrays. - */ - enum TickType { - /** - * CPU utilization that occurred while executing at the user level - * (application). - */ - USER(0), - /** - * CPU utilization that occurred while executing at the user level with nice - * priority. - */ - NICE(1), - /** - * CPU utilization that occurred while executing at the system level - * (kernel). - */ - SYSTEM(2), - /** - * Time that the CPU or CPUs were idle and the system did not have an - * outstanding disk I/O request. - */ - IDLE(3), - /** - * Time that the CPU or CPUs were idle during which the system had an - * outstanding disk I/O request. - */ - IOWAIT(4), - /** - * Time that the CPU used to service hardware IRQs - */ - IRQ(5), - /** - * Time that the CPU used to service soft IRQs - */ - SOFTIRQ(6), - /** - * Time which the hypervisor dedicated for other guests in the system. Only - * supported on Linux. - */ - STEAL(7); - - private int index; - - TickType(int value) { - this.index = value; - } - - /** - * @return The integer index of this ENUM in the processor tick arrays, - * which matches the output of Linux /proc/cpuinfo - */ - public int getIndex() { - return index; - } - } - /** * Processor vendor. * @@ -100,14 +40,6 @@ public int getIndex() { */ String getVendor(); - /** - * Set processor vendor. - * - * @param vendor - * Vendor. - */ - void setVendor(String vendor); - /** * Name, eg. Intel(R) Core(TM)2 Duo CPU T7300 @ 2.00GHz * @@ -115,14 +47,6 @@ public int getIndex() { */ String getName(); - /** - * Set processor name. - * - * @param name - * Name. - */ - void setName(String name); - /** * Vendor frequency (in Hz), eg. for processor named Intel(R) Core(TM)2 Duo * CPU T7300 @ 2.00GHz the vendor frequency is 2000000000. @@ -132,12 +56,18 @@ public int getIndex() { long getVendorFreq(); /** - * Set processor vendor frequency (in Hz). + * Maximum frequeny (in Hz), of the logical processors on this CPU. + * + * @return The max frequency or -1 if unknown. + */ + long getMaxFreq(); + + /** + * Current frequeny (in Hz), of the logical processors on this CPU. * - * @param freq - * Frequency. + * @return An array of processor frequency or -1 if unknown. */ - void setVendorFreq(long freq); + long[] getCurrentFreq(); /** * Gets the Processor ID. This is a hexidecimal string representing an @@ -154,14 +84,6 @@ public int getIndex() { */ String getProcessorID(); - /** - * Set processor ID - * - * @param processorID - * The processor ID - */ - void setProcessorID(String processorID); - /** * Identifier, eg. x86 Family 6 Model 15 Stepping 10. * @@ -169,14 +91,6 @@ public int getIndex() { */ String getIdentifier(); - /** - * Set processor identifier. - * - * @param identifier - * Identifier. - */ - void setIdentifier(String identifier); - /** * Is CPU 64bit? * @@ -184,61 +98,40 @@ public int getIndex() { */ boolean isCpu64bit(); - /** - * Set flag is cpu is 64bit. - * - * @param cpu64 - * True if cpu is 64. - */ - void setCpu64(boolean cpu64); - /** * @return the stepping */ String getStepping(); - /** - * @param stepping - * the stepping to set - */ - void setStepping(String stepping); - /** * @return the model */ String getModel(); - /** - * @param model - * the model to set - */ - void setModel(String model); - /** * @return the family */ String getFamily(); /** - * @param family - * the family to set + * Returns an array of the CPU's logical processors. + * + * @return The logical processor array. */ - void setFamily(String family); + LogicalProcessor[] getLogicalProcessors(); /** * Returns the "recent cpu usage" for the whole system by counting ticks - * from {@link #getSystemCpuLoadTicks()} between successive calls of this - * method, with a minimum interval slightly less than 1 second. If less than - * one second has elapsed since the last call of this method, it will return - * a calculation based on the tick counts and times of the previous two - * calls. If at least a second has elapsed, it will return the average CPU - * load for the interval and update the "last called" times. This method is - * intended to be used for periodic polling at intervals of 1 second or - * longer. - * + * from {@link #getSystemCpuLoadTicks()} between the user-provided value + * from a previous call. + * + * @param oldTicks + * A tick array from a previous call to + * {@link #getSystemCpuLoadTicks()} + * * @return CPU load between 0 and 1 (100%) */ - double getSystemCpuLoadBetweenTicks(); + double getSystemCpuLoadBetweenTicks(long[] oldTicks); /** * Get System-wide CPU Load tick counters. Returns an array with seven @@ -271,12 +164,13 @@ public int getIndex() { * period of time observed, while a value of 1.0 means that all CPUs were * actively running 100% of the time during the recent period being * observed. All values between 0.0 and 1.0 are possible depending of the - * activities going on in the system. If the system recent cpu usage is not - * available, the method returns a negative value. Calling this method - * immediately upon instantiating the {@link CentralProcessor} may give - * unreliable results. If a user is not running the Oracle JVM, this method - * will default to the behavior and return value of - * {@link #getSystemCpuLoadBetweenTicks()}. + * activities going on in the system. + *
+ * If the system recent cpu usage is not available, the method returns a
+ * negative value. Calling this method immediately upon instantiating the
+ * {@link CentralProcessor} may give unreliable results. Calling this method
+ * too frequently may return {@link Double#NaN}. If a user is not running
+ * the Oracle JVM, this method will return a negative value.
*
* @return the "recent cpu usage" for the whole system; a negative value if
* not available.
@@ -284,16 +178,6 @@ public int getIndex() {
@SuppressWarnings("restriction")
double getSystemCpuLoad();
- /**
- * Returns the system load average for the last minute. This is equivalent
- * to calling {@link CentralProcessor#getSystemLoadAverage(int)} with an
- * argument of 1 and returning the first value, and is retained for
- * compatibility.
- *
- * @return the system load average; or a negative value if not available.
- */
- double getSystemLoadAverage();
-
/**
* Returns the system load average for the number of elements specified, up
* to 3, representing 1, 5, and 15 minutes. The system load average is the
@@ -317,19 +201,16 @@ public int getIndex() {
/**
* Returns the "recent cpu usage" for all logical processors by counting
- * ticks for the processors from {@link #getProcessorCpuLoadTicks()} between
- * successive calls of this method, with a minimum interval slightly less
- * than 1 second. If less than one second has elapsed since the last call of
- * this method, it will return a calculation based on the tick counts and
- * times of the previous two calls. If at least a second has elapsed, it
- * will return the average CPU load for the interval and update the "last
- * called" times. This method is intended to be used for periodic polling
- * (iterating over all processors) at intervals of 1 second or longer.
+ * ticks from {@link #getProcessorCpuLoadTicks()} between the user-provided
+ * value from a previous call.
*
+ * @param oldTicks
+ * A tick array from a previous call to
+ * {@link #getProcessorCpuLoadTicks()}
* @return array of CPU load between 0 and 1 (100%) for each logical
* processor
*/
- double[] getProcessorCpuLoadBetweenTicks();
+ double[] getProcessorCpuLoadBetweenTicks(long[][] oldTicks);
/**
* Get Processor CPU Load tick counters. Returns a two dimensional array,
@@ -399,4 +280,134 @@ public int getIndex() {
* @return The number of interrupts
*/
long getInterrupts();
+
+ /**
+ * Update the values for the next call to the getters on this class.
+ */
+ void updateAttributes();
+
+ /**
+ * Index of CPU tick counters in the {@link #getSystemCpuLoadTicks()} and
+ * {@link #getProcessorCpuLoadTicks()} arrays.
+ */
+ enum TickType {
+ /**
+ * CPU utilization that occurred while executing at the user level
+ * (application).
+ */
+ USER(0),
+ /**
+ * CPU utilization that occurred while executing at the user level with
+ * nice priority.
+ */
+ NICE(1),
+ /**
+ * CPU utilization that occurred while executing at the system level
+ * (kernel).
+ */
+ SYSTEM(2),
+ /**
+ * Time that the CPU or CPUs were idle and the system did not have an
+ * outstanding disk I/O request.
+ */
+ IDLE(3),
+ /**
+ * Time that the CPU or CPUs were idle during which the system had an
+ * outstanding disk I/O request.
+ */
+ IOWAIT(4),
+ /**
+ * Time that the CPU used to service hardware IRQs
+ */
+ IRQ(5),
+ /**
+ * Time that the CPU used to service soft IRQs
+ */
+ SOFTIRQ(6),
+ /**
+ * Time which the hypervisor dedicated for other guests in the system.
+ * Only supported on Linux.
+ */
+ STEAL(7);
+
+ private int index;
+
+ TickType(int value) {
+ this.index = value;
+ }
+
+ /**
+ * @return The integer index of this ENUM in the processor tick arrays,
+ * which matches the output of Linux /proc/cpuinfo
+ */
+ public int getIndex() {
+ return index;
+ }
+ }
+
+ class LogicalProcessor implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private int processorNumber;
+ private int physicalProcessorNumber;
+ private int physicalPackageNumber;
+
+ /**
+ * The Logical Processor number as seen by the Operating System. Used
+ * for assigning process affinity and reporting CPU usage and other
+ * statistics.
+ *
+ * @return the processorNumber
+ */
+ public int getProcessorNumber() {
+ return processorNumber;
+ }
+
+ /**
+ * @param processorNumber
+ * the processorNumber to set
+ */
+ public void setProcessorNumber(int processorNumber) {
+ this.processorNumber = processorNumber;
+ }
+
+ /**
+ * The physical processor (core) id number assigned to this logical
+ * processor. Hyperthreaded logical processors which share the same
+ * physical processor will have the same number.
+ *
+ * @return the physicalProcessorNumber
+ */
+ public int getPhysicalProcessorNumber() {
+ return physicalProcessorNumber;
+ }
+
+ /**
+ * @param physicalProcessorNumber
+ * the physicalProcessorNumber to set
+ */
+ public void setPhysicalProcessorNumber(int physicalProcessorNumber) {
+ this.physicalProcessorNumber = physicalProcessorNumber;
+ }
+
+ /**
+ * The physical package (socket) id number assigned to this logical
+ * processor. Multicore CPU packages may have multiple physical
+ * processors which share the same number.
+ *
+ * @return the physicalPackageNumber
+ */
+ public int getPhysicalPackageNumber() {
+ return physicalPackageNumber;
+ }
+
+ /**
+ * @param physicalPackageNumber
+ * the physicalPackageNumber to set
+ */
+ public void setPhysicalPackageNumber(int physicalPackageNumber) {
+ this.physicalPackageNumber = physicalPackageNumber;
+ }
+ }
}
diff --git a/oshi-core/src/main/java/oshi/hardware/common/AbstractCentralProcessor.java b/oshi-core/src/main/java/oshi/hardware/common/AbstractCentralProcessor.java
index 599a6ef54b0..bf5486c9579 100644
--- a/oshi-core/src/main/java/oshi/hardware/common/AbstractCentralProcessor.java
+++ b/oshi-core/src/main/java/oshi/hardware/common/AbstractCentralProcessor.java
@@ -34,11 +34,7 @@
import oshi.util.ParseUtil;
/**
- * A CPU as defined in Linux /proc.
- *
- * @author alessandro[at]perucchi[dot]org
- * @author alessio.fachechi[at]gmail[dot]com
- * @author widdis[at]gmail[dot]com
+ * A CPU.
*/
@SuppressWarnings("restriction")
public abstract class AbstractCentralProcessor implements CentralProcessor {
@@ -53,160 +49,168 @@ public abstract class AbstractCentralProcessor implements CentralProcessor {
private static final java.lang.management.OperatingSystemMXBean OS_MXBEAN = ManagementFactory
.getOperatingSystemMXBean();
- /**
- * Calling OperatingSystemMxBean too rapidly results in NaN. Store the
- * latest value to return if polling is too rapid
- */
- private double lastCpuLoad = 0d;
-
- /**
- * Keep track of last CPU Load poll to OperatingSystemMXBean to ensure
- * enough time has elapsed
- */
- private long lastCpuLoadTime = 0;
-
/**
* Keep track whether MXBean supports Oracle JVM methods
*/
- private boolean sunMXBean = false;
+ private static boolean sunMXBean = false;
+ static {
+ try {
+ Class.forName("com.sun.management.OperatingSystemMXBean");
+ LOG.debug("Oracle MXBean detected.");
+ sunMXBean = true;
+ } catch (ClassNotFoundException | ClassCastException e) {
+ LOG.debug("Oracle MXBean not detected.");
+ }
+ }
// Logical and Physical Processor Counts
- protected int logicalProcessorCount = 0;
-
- protected int physicalProcessorCount = 0;
-
protected int physicalPackageCount = 0;
+ protected int physicalProcessorCount = 0;
+ protected int logicalProcessorCount = 0;
- // Maintain previous ticks to be used for calculating usage between them.
// System ticks
- private long tickTime;
-
- private long[] prevTicks;
-
- private long[] curTicks;
-
+ protected long[] systemCpuLoadTicks;
// Per-processor ticks [cpu][type]
- private long procTickTime;
-
- private long[][] prevProcTicks;
-
- private long[][] curProcTicks;
+ private long[][] processorCpuLoadTicks;
// Processor info
private String cpuVendor;
-
private String cpuName;
-
private String processorID;
-
private String cpuIdentifier;
-
private String cpuStepping;
-
private String cpuModel;
-
private String cpuFamily;
-
- private Long cpuVendorFreq;
-
+ private long cpuVendorFreq;
+ private long cpuMaxFreq;
+ private long[] cpuCurrentFreq;
private Boolean cpu64;
+ private LogicalProcessor[] logicalProcessors;
/**
* Create a Processor
*/
public AbstractCentralProcessor() {
- initMXBean();
- // Initialize processor counts
- calculateProcessorCounts();
+ // Initialize processor counts and populate logical processor array
+ this.logicalProcessors = initProcessorCounts();
}
/**
- * Initializes mxBean boolean
+ * Updates logical and physical processor counts and arrays
*/
- private void initMXBean() {
- try {
- Class.forName("com.sun.management.OperatingSystemMXBean");
- // Initialize CPU usage
- this.lastCpuLoad = ((com.sun.management.OperatingSystemMXBean) OS_MXBEAN).getSystemCpuLoad();
- this.lastCpuLoadTime = System.currentTimeMillis();
- this.sunMXBean = true;
- LOG.debug("Oracle MXBean detected.");
- } catch (ClassNotFoundException | ClassCastException e) {
- LOG.debug("Oracle MXBean not detected.");
- LOG.trace("{}", e);
- }
+ protected abstract LogicalProcessor[] initProcessorCounts();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public LogicalProcessor[] getLogicalProcessors() {
+ return this.logicalProcessors;
}
/**
- * Initializes tick arrays
+ * {@inheritDoc}
*/
- protected synchronized void initTicks() {
- this.prevProcTicks = new long[this.logicalProcessorCount][TickType.values().length];
- this.curProcTicks = new long[this.logicalProcessorCount][TickType.values().length];
- this.prevTicks = new long[TickType.values().length];
- this.curTicks = new long[TickType.values().length];
+ @Override
+ public long[] getSystemCpuLoadTicks() {
+ if (this.systemCpuLoadTicks == null) {
+ this.systemCpuLoadTicks = querySystemCpuLoadTicks();
+ }
+ return this.systemCpuLoadTicks;
}
/**
- * Updates logical and physical processor counts
+ * Get System-wide CPU Load tick counters.
+ *
+ * @return The tick counters.
*/
- protected abstract void calculateProcessorCounts();
+ protected abstract long[] querySystemCpuLoadTicks();
/**
* {@inheritDoc}
*/
@Override
- public String getVendor() {
- if (this.cpuVendor == null) {
- setVendor("");
+ public long[] getCurrentFreq() {
+ if (this.cpuCurrentFreq == null) {
+ this.cpuCurrentFreq = queryCurrentFreq();
}
- return this.cpuVendor;
+ return this.cpuCurrentFreq;
}
+ /**
+ * Get per processor current frequencies.
+ *
+ * @return The current frequencies.
+ */
+ protected abstract long[] queryCurrentFreq();
+
/**
* {@inheritDoc}
*/
@Override
- public void setVendor(String vendor) {
- this.cpuVendor = vendor;
+ public long getMaxFreq() {
+ if (this.cpuMaxFreq == 0) {
+ this.cpuMaxFreq = queryMaxFreq();
+ }
+ return this.cpuMaxFreq;
}
+ /**
+ * Get processor max frequency.
+ *
+ * @return The max frequency.
+ */
+ protected abstract long queryMaxFreq();
+
/**
* {@inheritDoc}
*/
@Override
- public String getName() {
- if (this.cpuName == null) {
- setName("");
+ public long[][] getProcessorCpuLoadTicks() {
+ if (processorCpuLoadTicks == null) {
+ this.processorCpuLoadTicks = queryProcessorCpuLoadTicks();
}
- return this.cpuName;
+ return this.processorCpuLoadTicks;
}
+ /**
+ * Get Per-Processor CPU Load tick counters.
+ *
+ * @return The tick counters.
+ */
+ protected abstract long[][] queryProcessorCpuLoadTicks();
+
/**
* {@inheritDoc}
*/
@Override
- public void setName(String name) {
- this.cpuName = name;
+ public String getVendor() {
+ if (this.cpuVendor == null) {
+ setVendor("");
+ }
+ return this.cpuVendor;
}
/**
* {@inheritDoc}
*/
@Override
- public String getProcessorID() {
- if (this.processorID == null) {
- setProcessorID("");
+ public String getName() {
+ if (this.cpuName == null) {
+ setName("");
}
- return this.processorID;
+ return this.cpuName;
}
/**
* {@inheritDoc}
*/
@Override
- public void setProcessorID(String processorID) {
- this.processorID = processorID;
+ public String getProcessorID() {
+ if (this.processorID == null) {
+ setProcessorID("");
+ }
+ return this.processorID;
}
/**
@@ -214,26 +218,18 @@ public void setProcessorID(String processorID) {
*/
@Override
public long getVendorFreq() {
- if (this.cpuVendorFreq == null) {
+ if (this.cpuVendorFreq == 0) {
Pattern pattern = Pattern.compile("@ (.*)$");
Matcher matcher = pattern.matcher(getName());
if (matcher.find()) {
String unit = matcher.group(1);
- this.cpuVendorFreq = Long.valueOf(ParseUtil.parseHertz(unit));
+ this.cpuVendorFreq = ParseUtil.parseHertz(unit);
} else {
- this.cpuVendorFreq = Long.valueOf(-1L);
+ this.cpuVendorFreq = -1L;
}
}
- return this.cpuVendorFreq.longValue();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setVendorFreq(long freq) {
- this.cpuVendorFreq = Long.valueOf(freq);
+ return this.cpuVendorFreq;
}
/**
@@ -256,14 +252,6 @@ public String getIdentifier() {
return this.cpuIdentifier;
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void setIdentifier(String identifier) {
- this.cpuIdentifier = identifier;
- }
-
/**
* {@inheritDoc}
*/
@@ -275,14 +263,6 @@ public boolean isCpu64bit() {
return this.cpu64;
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void setCpu64(boolean value) {
- this.cpu64 = Boolean.valueOf(value);
- }
-
/**
* {@inheritDoc}
*/
@@ -297,14 +277,6 @@ public String getStepping() {
return this.cpuStepping;
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void setStepping(String stepping) {
- this.cpuStepping = stepping;
- }
-
/**
* {@inheritDoc}
*/
@@ -319,14 +291,6 @@ public String getModel() {
return this.cpuModel;
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void setModel(String model) {
- this.cpuModel = model;
- }
-
/**
* {@inheritDoc}
*/
@@ -342,11 +306,75 @@ public String getFamily() {
}
/**
- * {@inheritDoc}
+ * @param cpuVendor
+ * the cpuVendor to set
*/
- @Override
- public void setFamily(String family) {
- this.cpuFamily = family;
+ protected void setVendor(String cpuVendor) {
+ this.cpuVendor = cpuVendor;
+ }
+
+ /**
+ * @param cpuName
+ * the cpuName to set
+ */
+ protected void setName(String cpuName) {
+ this.cpuName = cpuName;
+ }
+
+ /**
+ * @param cpuIdentifier
+ * the cpuIdentifier to set
+ */
+ protected void setIdentifier(String cpuIdentifier) {
+ this.cpuIdentifier = cpuIdentifier;
+ }
+
+ /**
+ * @param cpuStepping
+ * the cpuStepping to set
+ */
+ protected void setStepping(String cpuStepping) {
+ this.cpuStepping = cpuStepping;
+ }
+
+ /**
+ * @param cpuModel
+ * the cpuModel to set
+ */
+ protected void setModel(String cpuModel) {
+ this.cpuModel = cpuModel;
+ }
+
+ /**
+ * @param cpuFamily
+ * the cpuFamily to set
+ */
+ protected void setFamily(String cpuFamily) {
+ this.cpuFamily = cpuFamily;
+ }
+
+ /**
+ * @param cpuVendorFreq
+ * the cpuVendorFreq to set
+ */
+ protected void setVendorFreq(Long cpuVendorFreq) {
+ this.cpuVendorFreq = cpuVendorFreq;
+ }
+
+ /**
+ * @param cpu64
+ * the cpu64 to set
+ */
+ protected void setCpu64(Boolean cpu64) {
+ this.cpu64 = cpu64;
+ }
+
+ /**
+ * @param processorID
+ * the processorID to set
+ */
+ protected void setProcessorID(String processorID) {
+ this.processorID = processorID;
}
/**
@@ -374,103 +402,56 @@ private String parseIdentifier(String id) {
* {@inheritDoc}
*/
@Override
- public synchronized double getSystemCpuLoadBetweenTicks() {
- // Check if > ~ 0.95 seconds since last tick count.
- long now = System.currentTimeMillis();
- LOG.trace("Current time: {} Last tick time: {}", now, this.tickTime);
- if (now - this.tickTime > 950) {
- // Enough time has elapsed.
- updateSystemTicks();
+ public synchronized double getSystemCpuLoadBetweenTicks(long[] oldTicks) {
+ if (oldTicks.length != TickType.values().length) {
+ throw new IllegalArgumentException(
+ "Tick array " + oldTicks.length + " should have " + TickType.values().length + " elements");
}
+ long[] ticks = getSystemCpuLoadTicks();
// Calculate total
long total = 0;
- for (int i = 0; i < this.curTicks.length; i++) {
- total += this.curTicks[i] - this.prevTicks[i];
+ for (int i = 0; i < ticks.length; i++) {
+ total += ticks[i] - oldTicks[i];
}
// Calculate idle from difference in idle and IOwait
- long idle = this.curTicks[TickType.IDLE.getIndex()] + this.curTicks[TickType.IOWAIT.getIndex()]
- - this.prevTicks[TickType.IDLE.getIndex()] - this.prevTicks[TickType.IOWAIT.getIndex()];
+ long idle = ticks[TickType.IDLE.getIndex()] + ticks[TickType.IOWAIT.getIndex()]
+ - oldTicks[TickType.IDLE.getIndex()] - oldTicks[TickType.IOWAIT.getIndex()];
LOG.trace("Total ticks: {} Idle ticks: {}", total, idle);
return total > 0 && idle >= 0 ? (double) (total - idle) / total : 0d;
}
- /**
- * Updates system tick information. Stores in array with seven elements
- * representing clock ticks or milliseconds (platform dependent) spent in
- * User (0), Nice (1), System (2), Idle (3), IOwait (4), IRQ (5), and
- * SoftIRQ (6) states. By measuring the difference between ticks across a
- * time interval, CPU load over that interval may be calculated.
- */
- protected void updateSystemTicks() {
- LOG.trace("Updating System Ticks");
- long[] ticks = getSystemCpuLoadTicks();
- // Skip update if ticks is all zero.
- // Iterate to find a nonzero tick value and return; this should quickly
- // find a nonzero value if one exists and be fast in checking 0's
- // through branch prediction if it doesn't
- for (long tick : ticks) {
- if (tick != 0) {
- // We have a nonzero tick array, update and return!
- this.tickTime = System.currentTimeMillis();
- // Copy to previous
- System.arraycopy(this.curTicks, 0, this.prevTicks, 0, this.curTicks.length);
- System.arraycopy(ticks, 0, this.curTicks, 0, ticks.length);
- return;
- }
- }
- }
-
/**
* {@inheritDoc}
*/
@Override
public double getSystemCpuLoad() {
- if (this.sunMXBean) {
- long now = System.currentTimeMillis();
- // If called too recently, return latest value
- if (now - this.lastCpuLoadTime < 200) {
- return this.lastCpuLoad;
- }
- this.lastCpuLoad = ((com.sun.management.OperatingSystemMXBean) OS_MXBEAN).getSystemCpuLoad();
- this.lastCpuLoadTime = now;
- return this.lastCpuLoad;
+ if (sunMXBean) {
+ return ((com.sun.management.OperatingSystemMXBean) OS_MXBEAN).getSystemCpuLoad();
}
- return getSystemCpuLoadBetweenTicks();
+ return -1.0;
}
/**
* {@inheritDoc}
*/
@Override
- public double getSystemLoadAverage() {
- return getSystemLoadAverage(1)[0];
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public double[] getProcessorCpuLoadBetweenTicks() {
- // Check if > ~ 0.95 seconds since last tick count.
- long now = System.currentTimeMillis();
- LOG.trace("Current time: {} Last tick time: {}", now, this.procTickTime);
- if (now - this.procTickTime > 950) {
- // Enough time has elapsed.
- // Update latest
- updateProcessorTicks();
+ public double[] getProcessorCpuLoadBetweenTicks(long[][] oldTicks) {
+ if (oldTicks.length != this.logicalProcessorCount || oldTicks[0].length != TickType.values().length) {
+ throw new IllegalArgumentException(
+ "Tick array " + oldTicks.length + " should have " + this.logicalProcessorCount
+ + " arrays, each of which has " + TickType.values().length + " elements");
}
+ long[][] ticks = getProcessorCpuLoadTicks();
double[] load = new double[this.logicalProcessorCount];
for (int cpu = 0; cpu < this.logicalProcessorCount; cpu++) {
long total = 0;
- for (int i = 0; i < this.curProcTicks[cpu].length; i++) {
- total += this.curProcTicks[cpu][i] - this.prevProcTicks[cpu][i];
+ for (int i = 0; i < ticks[cpu].length; i++) {
+ total += ticks[cpu][i] - oldTicks[cpu][i];
}
// Calculate idle from difference in idle and IOwait
- long idle = this.curProcTicks[cpu][TickType.IDLE.getIndex()]
- + this.curProcTicks[cpu][TickType.IOWAIT.getIndex()]
- - this.prevProcTicks[cpu][TickType.IDLE.getIndex()]
- - this.prevProcTicks[cpu][TickType.IOWAIT.getIndex()];
+ long idle = ticks[cpu][TickType.IDLE.getIndex()] + ticks[cpu][TickType.IOWAIT.getIndex()]
+ - oldTicks[cpu][TickType.IDLE.getIndex()] - oldTicks[cpu][TickType.IOWAIT.getIndex()];
LOG.trace("CPU: {} Total ticks: {} Idle ticks: {}", cpu, total, idle);
// update
load[cpu] = total > 0 && idle >= 0 ? (double) (total - idle) / total : 0d;
@@ -478,40 +459,6 @@ public double[] getProcessorCpuLoadBetweenTicks() {
return load;
}
- /**
- * Updates per-processor tick information. Stores in 2D array; an array for
- * each logical processor with with seven elements representing clock ticks
- * or milliseconds (platform dependent) spent in User (0), Nice (1), System
- * (2), Idle (3), IOwait (4), IRQ (5), and SoftIRQ (6) states. By measuring
- * the difference between ticks across a time interval, CPU load over that
- * interval may be calculated.
- */
- protected void updateProcessorTicks() {
- LOG.trace("Updating Processor Ticks");
- long[][] ticks = getProcessorCpuLoadTicks();
- // Skip update if ticks is all zero.
- // Iterate to find a nonzero tick value and return; this should quickly
- // find a nonzero value if one exists and be fast in checking 0's
- // through branch prediction if it doesn't
- for (long[] tick : ticks) {
- for (long element : tick) {
- if (element != 0L) {
- // We have a nonzero tick array, update and return!
- this.procTickTime = System.currentTimeMillis();
- // Copy to previous
- for (int cpu = 0; cpu < this.logicalProcessorCount; cpu++) {
- System.arraycopy(this.curProcTicks[cpu], 0, this.prevProcTicks[cpu], 0,
- this.curProcTicks[cpu].length);
- }
- for (int cpu = 0; cpu < this.logicalProcessorCount; cpu++) {
- System.arraycopy(ticks[cpu], 0, this.curProcTicks[cpu], 0, ticks[cpu].length);
- }
- return;
- }
- }
- }
- }
-
/**
* {@inheritDoc}
*/
@@ -570,7 +517,7 @@ protected String createProcessorID(String stepping, String model, String family,
processorIdBytes |= (familyL & 0xf0) << 20;
// 13:12 – Processor Type, assume 0
for (String flag : flags) {
- switch (flag) {
+ switch (flag) { // NOSONAR squid:S1479
case "fpu":
processorIdBytes |= 1L << 32;
break;
@@ -667,4 +614,15 @@ protected String createProcessorID(String stepping, String model, String family,
}
return String.format("%016X", processorIdBytes);
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void updateAttributes() {
+ this.systemCpuLoadTicks = null;
+ this.processorCpuLoadTicks = null;
+ this.cpuCurrentFreq = null;
+ }
+
}
diff --git a/oshi-core/src/main/java/oshi/hardware/platform/linux/LinuxCentralProcessor.java b/oshi-core/src/main/java/oshi/hardware/platform/linux/LinuxCentralProcessor.java
index 5746687d9d6..e25018e50b4 100644
--- a/oshi-core/src/main/java/oshi/hardware/platform/linux/LinuxCentralProcessor.java
+++ b/oshi-core/src/main/java/oshi/hardware/platform/linux/LinuxCentralProcessor.java
@@ -23,6 +23,7 @@
*/
package oshi.hardware.platform.linux;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -50,6 +51,9 @@ public class LinuxCentralProcessor extends AbstractCentralProcessor {
private static final Logger LOG = LoggerFactory.getLogger(LinuxCentralProcessor.class);
+ // See https://www.kernel.org/doc/Documentation/cpu-freq/user-guide.txt
+ private static final String CPUFREQ_PATH = "/sys/devices/system/cpu/cpu";
+
/**
* Create a Processor
*/
@@ -57,8 +61,6 @@ public LinuxCentralProcessor() {
super();
// Initialize class variables
initVars();
- // Initialize tick arrays
- initTicks();
LOG.debug("Initialized Processor");
}
@@ -109,37 +111,46 @@ private void initVars() {
* Updates logical and physical processor counts from /proc/cpuinfo
*/
@Override
- protected void calculateProcessorCounts() {
- int[] uniqueID = new int[2];
- uniqueID[0] = -1;
- uniqueID[1] = -1;
-
+ protected LogicalProcessor[] initProcessorCounts() {
Set