On windows, process startTime is not equals to ProcessHandle().info().startInstant()
public static void main(final String[] args) {
System.out.println("Start");
final OperatingSystem operatingSystem = new SystemInfo().getOperatingSystem();
ProcessHandle.allProcesses().filter(p -> p.info().startInstant().isPresent()).forEach(p -> {
final OSProcess oshiProcess = operatingSystem.getProcess((int) p.pid());
final Instant processInstant = p.info().startInstant().orElseThrow();
final Instant oshiInstant = Instant.ofEpochMilli(oshiProcess.getStartTime());
if (processInstant.equals(oshiInstant)) {
System.out.println("Same");
} else {
final long deltaMilli = oshiInstant.toEpochMilli() - processInstant.toEpochMilli();
System.out.println(deltaMilli + " milli delta " + oshiInstant + " - " + processInstant);
}
});
System.out.println("End");
}
Start
5 milli delta 2020-07-15T04:47:37.022Z - 2020-07-15T04:47:37.017Z
2 milli delta 2020-07-15T04:47:37.045Z - 2020-07-15T04:47:37.043Z
3 milli delta 2020-07-15T04:47:37.086Z - 2020-07-15T04:47:37.083Z
2 milli delta 2020-07-15T04:47:37.168Z - 2020-07-15T04:47:37.166Z
3 milli delta 2020-07-15T04:47:37.503Z - 2020-07-15T04:47:37.500Z
3 milli delta 2020-07-15T04:47:38.072Z - 2020-07-15T04:47:38.069Z
2 milli delta 2020-07-15T04:47:38.670Z - 2020-07-15T04:47:38.668Z
1 milli delta 2020-07-15T04:47:38.905Z - 2020-07-15T04:47:38.904Z
1 milli delta 2020-07-15T04:47:39.291Z - 2020-07-15T04:47:39.290Z
1 milli delta 2020-07-15T04:47:39.461Z - 2020-07-15T04:47:39.460Z
1 milli delta 2020-07-15T04:47:39.948Z - 2020-07-15T04:47:39.947Z
1 milli delta 2020-07-15T04:47:40.156Z - 2020-07-15T04:47:40.155Z
2 milli delta 2020-07-15T04:47:40.939Z - 2020-07-15T04:47:40.937Z
1 milli delta 2020-07-15T04:47:41.208Z - 2020-07-15T04:47:41.207Z
1 milli delta 2020-07-15T04:47:44.124Z - 2020-07-15T04:47:44.123Z
2 milli delta 2020-07-15T04:47:47.081Z - 2020-07-15T04:47:47.079Z
3 milli delta 2020-07-15T04:47:51.486Z - 2020-07-15T04:47:51.483Z
2 milli delta 2020-07-15T04:47:51.928Z - 2020-07-15T04:47:51.926Z
2 milli delta 2020-07-15T04:47:52.649Z - 2020-07-15T04:47:52.647Z
2 milli delta 2020-07-15T04:47:53.959Z - 2020-07-15T04:47:53.957Z
2 milli delta 2020-07-15T04:47:54.101Z - 2020-07-15T04:47:54.099Z
2 milli delta 2020-07-15T04:47:54.567Z - 2020-07-15T04:47:54.565Z
2 milli delta 2020-07-15T04:47:55.149Z - 2020-07-15T04:47:55.147Z
2 milli delta 2020-07-15T04:48:13.603Z - 2020-07-15T04:48:13.601Z
2 milli delta 2020-07-15T04:48:15.259Z - 2020-07-15T04:48:15.257Z
2 milli delta 2020-07-15T04:48:53.523Z - 2020-07-15T04:48:53.521Z
2 milli delta 2020-07-15T04:49:39.656Z - 2020-07-15T04:49:39.654Z
2 milli delta 2020-07-15T04:49:54.703Z - 2020-07-15T04:49:54.701Z
1 milli delta 2020-07-15T04:50:29.008Z - 2020-07-15T04:50:29.007Z
1 milli delta 2020-07-15T04:50:29.010Z - 2020-07-15T04:50:29.009Z
1 milli delta 2020-07-15T04:50:58.988Z - 2020-07-15T04:50:58.987Z
2 milli delta 2020-07-15T04:52:42.591Z - 2020-07-15T04:52:42.589Z
1 milli delta 2020-07-15T04:53:42.127Z - 2020-07-15T04:53:42.126Z
2 milli delta 2020-07-15T04:53:42.187Z - 2020-07-15T04:53:42.185Z
2 milli delta 2020-07-15T04:53:42.295Z - 2020-07-15T04:53:42.293Z
1 milli delta 2020-07-15T04:53:42.314Z - 2020-07-15T04:53:42.313Z
1 milli delta 2020-07-15T04:53:42.422Z - 2020-07-15T04:53:42.421Z
1 milli delta 2020-07-15T04:53:42.518Z - 2020-07-15T04:53:42.517Z
1 milli delta 2020-07-15T04:53:42.554Z - 2020-07-15T04:53:42.553Z
1 milli delta 2020-07-15T04:53:42.588Z - 2020-07-15T04:53:42.587Z
1 milli delta 2020-07-15T04:54:02.978Z - 2020-07-15T04:54:02.977Z
1 milli delta 2020-07-15T04:57:42.372Z - 2020-07-15T04:57:42.371Z
1 milli delta 2020-07-15T04:58:54.476Z - 2020-07-15T04:58:54.475Z
2 milli delta 2020-07-15T05:37:43.781Z - 2020-07-15T05:37:43.779Z
1 milli delta 2020-07-15T05:44:38.584Z - 2020-07-15T05:44:38.583Z
2 milli delta 2020-07-15T05:44:39.490Z - 2020-07-15T05:44:39.488Z
2 milli delta 2020-07-15T06:09:15.083Z - 2020-07-15T06:09:15.081Z
1 milli delta 2020-07-15T06:10:16.633Z - 2020-07-15T06:10:16.632Z
2 milli delta 2020-07-15T06:20:21.683Z - 2020-07-15T06:20:21.681Z
2 milli delta 2020-07-15T06:20:32.777Z - 2020-07-15T06:20:32.775Z
1 milli delta 2020-07-15T06:41:11.321Z - 2020-07-15T06:41:11.320Z
1 milli delta 2020-07-15T06:41:23.419Z - 2020-07-15T06:41:23.418Z
2 milli delta 2020-07-15T07:25:59.846Z - 2020-07-15T07:25:59.844Z
1 milli delta 2020-07-15T07:26:04.230Z - 2020-07-15T07:26:04.229Z
1 milli delta 2020-07-15T07:27:08.536Z - 2020-07-15T07:27:08.535Z
End
No delta on unix.
What's a few milliseconds between friends? :)
OSHI derives the process start time from the registry's HKEY_PERFORMANCE_DATA. This is equivalent to grabbing the value from the Process Performance Counters.
Java 9+'s ProcessHandle gets the start time from the GetProcessTimes() function.
The counters used in both cases are in 100-nanosecond units (Windows FILETIME), converted to milliseconds.
I don't know which one is more authoritative, given that the windows clock ticks are in 1/64 second increments (15.625 milliseconds). ~It appears from this page that the performance counters are less accurate (10 to 16 ms resolution is mentioned) for performance reasons.~
Given that OSHI targets Java 8, and we are already fetching the start time along with other process data (and it's in the same clock-tick units as the user and kernel time used for % CPU calculations) I'm content with the situation as-is.
Do you need more precision on these start times?
Hmm, it's not a matter of precision. I compared the elapsed time between the various timestamps and it's almost always exactly equal, plus or minus a millisecond. And it's very consistent with the counter shortly after the process times value.
Somewhere internally in Windows, it's recording one start time in one location (getProcessTimes), and a few milliseconds later, recording a different start time in a different location (counters). Since both times are probably recorded as part of the "startup routine" of a process, I suspect an argument can be made that they're both correct, depending on your interpretation of exactly when a process is started.
I could replicate the ProcessHandle code in OSHI using JNA but it'd be a lot less efficient than the JDK's native implementation. Maybe this would be a good use case for a multi-release JAR.
In our program we need to retreive ProcessHandle from oshi process and ProcessHandle equality is defined by same pid and same startInstant.
Code from openjdk
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof ProcessHandleImpl) {
ProcessHandleImpl other = (ProcessHandleImpl) obj;
return (pid == other.pid) &&
(startTime == other.startTime
|| startTime == 0
|| other.startTime == 0);
}
return false;
}
equality is defined by same pid and same startInstant.
(Or a startInstant of 0, apparently.)
Since OSHI doesn't produce that type of object we/you are free to define equality however we wish, and I think PID equality (and possibly parent PID equality) along with an an "approximately equal" (similar to floating point equality within some epsilon) startInstant would be sufficient. You could simply:
Some observations after more research:
System.currentMillis() either before or after (or both & average) the timestamp to attempt to get an "accurate" uptime.So user and kernel time are probably similar in both (they increment in 1-tick units of 15.625 ms). Uptime is more accurate in the performance counter, and start time probably "matches wall clock time" in the JDK version.
ProcessHandle seems like a good new feature.Umm... ok. After digging into this... there's no difference in the raw data. This is a bug in OSHI... while I have a 100ns perf time counter available, we just subtract off "now" captured from System.currentTimeMillis().
So this is an easily fixable problem.....
OK, #1302 should fix this. It's updated in SNAPSHOT, can you test?
For better compatibility with ProcessHandle change pid type from int to long ?
change pid type from int to long
Unfortunately that would break the API.
It's a good idea, though, since the PID on AIX is long internally and while Windows is 32-bit, it's unsigned. But it would require a major version bump and that's probably not happening for a while.
Also I just updated the SNAPSHOT. There was still some rounding happening before some unnecessary subtraction which could have led to an off-by-1ms issue. I'm now directly storing the creation time so it should exactly match.