Skip to content

Commit

Permalink
Get Linux HZ from system config (#685)
Browse files Browse the repository at this point in the history
  • Loading branch information
dbwiddis committed Nov 20, 2018
1 parent 7e5f288 commit 8c0fa6d
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 65 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
3.11.0 (in progress)
================
* [#685](https://github.com/oshi/oshi/pull/685): Get Linux HZ from system config - [@dbwiddis](https://github.com/dbwiddis).
* Your contribution here.

3.10.0 (11/03/18)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import com.sun.jna.Native;
import com.sun.jna.Pointer;

import oshi.hardware.CentralProcessor.TickType;
import oshi.jna.platform.linux.Libc;
import oshi.jna.platform.linux.Libc.Sysinfo;
import oshi.software.common.AbstractOperatingSystem;
Expand Down Expand Up @@ -103,11 +102,24 @@ public int getOrder() {
private transient LinuxUserGroupInfo userGroupInfo = new LinuxUserGroupInfo();

// Jiffies per second, used for process time counters.
private static final long USER_HZ = calcHz();
// Boot time in MS. Cast/truncation is effectively rounding. Boot time could
// be +/- 5 ms due to System Uptime rounding to nearest 10ms.
private static final long BOOT_TIME = System.currentTimeMillis()
- 10L * (long) (100 * ProcUtil.getSystemUptimeSeconds() + 0.5);
private static final long USER_HZ = ParseUtil.parseLongOrDefault(ExecutingCommand.getFirstAnswer("getconf CLK_TCK"),
100L);
// Boot time in MS.
private static final long BOOT_TIME;
static {
// Uptime is only in hundredths of seconds but we need thousandths.
// We can grab uptime twice and take average to reduce error, getting
// current time in between
double uptime = ProcUtil.getSystemUptimeSeconds();
long now = System.currentTimeMillis();
uptime += ProcUtil.getSystemUptimeSeconds();
// Uptime is now 2x seconds, so divide by 2, but
// we want milliseconds so multiply by 1000
// Ultimately multiply by 1000/2 = 500
BOOT_TIME = now - (long) (500L * uptime + 0.5);
// Cast/truncation is effectively rounding. Boot time could
// be +/- 5 ms due to System Uptime rounding to nearest 10ms.
}

public LinuxOperatingSystem() {
this.manufacturer = "GNU/Linux";
Expand Down Expand Up @@ -636,46 +648,10 @@ private static String filenameToFamily(String name) {
* Gets Jiffies per second, useful for converting ticks to milliseconds and
* vice versa.
*
* @return Jiffies per second if it can be calculated. If not, returns 1000
* which assumes jiffies equal milliseconds.
* @return Jiffies per second.
*/
public static long getHz() {
return USER_HZ;
}

/**
* Calculates Jiffies per second, useful for converting ticks to
* milliseconds and vice versa.
*
* @return Jiffies per second if it can be calculated. If not, returns 1000
* which assumes jiffies equal milliseconds.
*/
private static long calcHz() {
// Grab idle time before fetching ticks
double idleSecsSinceBoot = ProcUtil.getSystemIdletimeSeconds();
long[] ticks = ProcUtil.getSystemCpuLoadTicks();
// Grab idle time again. We would normally divide by 2 here to get an
// average, but will use the doubled value in the calculation later for
// rounding to a multiple of 2
idleSecsSinceBoot += ProcUtil.getSystemIdletimeSeconds();

// Calculations convert ticks per second to milliseconds by multiplying
// by 1000/Hz. If we failed to fetch the idle time or idle ticks, by
// returning 1000 here we simply remove the conversion factor.
if (idleSecsSinceBoot <= 0d || ticks[TickType.IDLE.getIndex()] <= 0L) {
LOG.warn("Couldn't calculate jiffies per second. "
+ "Process time values are in jiffies, not milliseconds.");
return 1000L;
}

// Divide ticks in the idle process by seconds in the idle process. Per
// http://man7.org/linux/man-pages/man5/proc.5.html this is the USER_HZ
// value. Note we added the seconds calculations before/after fetching
// proc/stat so the initial division (by 2x seconds) will result in half
// of the eventual hz value. We round to the nearest integer by adding
// 0.5 and casting to long. Then we multiply by 2, so the final Hz value
// returned is rounded to the nearest even number.
return 2L * (long) (ticks[TickType.IDLE.getIndex()] / idleSecsSinceBoot + 0.5d);
}

}
22 changes: 0 additions & 22 deletions oshi-core/src/main/java/oshi/util/platform/linux/ProcUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,28 +58,6 @@ public static double getSystemUptimeSeconds() {
}
}

/**
* Parses the second value in /proc/uptime for seconds in the idle process
* since boot
*
* @return Seconds since boot in idle (if multiple processors, will probably
* exceed uptime)
*/
public static double getSystemIdletimeSeconds() {
String uptime = FileUtil.getStringFromFile("/proc/uptime");
int spaceIndex = uptime.indexOf(' ');
try {
if (spaceIndex < 0) {
// No space, error
return 0d;
} else {
return Double.parseDouble(uptime.substring(spaceIndex + 1));
}
} catch (NumberFormatException | IndexOutOfBoundsException e) {
return 0d;
}
}

/**
* Gets the CPU ticks array from /proc/stat
*
Expand Down

0 comments on commit 8c0fa6d

Please sign in to comment.