I've been investigating the best approach to achieve the following data for a specific process:
I decided to go with OSHI (Operating system & hardware information) API. Unfortunate for me , this API isn't giving me the desired info out of the box, it requires some basic knowledge of how to calculate , for example the cpu usage per process.
My Question is: How can I get the memory, disk, network usage by process id ?
using the following example of cpu usage data per prcoess
For example:
To get the actual CPU usage of a claculator.exe running process:
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.software.os.OSProcess;
import oshi.software.os.OperatingSystem;
public class processCPUusage {
public static void main(String[] args) throws InterruptedException {
OSProcess process;
long currentTime,previousTime = 0,timeDifference;
double cpu;
int pid = 7132;
SystemInfo si = new SystemInfo();
OperatingSystem os = si.getOperatingSystem();
CentralProcessor processor = si.getHardware().getProcessor();
int cpuNumber = processor.getLogicalProcessorCount();
boolean processExists = true;
while (processExists) {
process = os.getProcess(pid); // calculator.exe process id
if (process != null) {
// CPU
currentTime = process.getKernelTime() + process.getUserTime();
if (previousTime != -1) {
// If we have both a previous and a current time
// we can calculate the CPU usage
timeDifference = currentTime - previousTime;
cpu = (100d * (timeDifference / ((double) 1000))) / cpuNumber;
System.out.println(cpu);
}
previousTime = currentTime;
Thread.sleep(1000);
} else {
processExists = false;
}
}
}
}
The framework I'm using https://github.com/oshi/oshi/tree/master/src/site/markdown demonstrates the desired functionality but lacks proper examples
OSHI library + slf4j
<dependency>
<groupId>com.github.dblock</groupId>
<artifactId>oshi-core</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
The original answer in 2017 below is now out of date. The OSProcess
class now has many more methods that mostly answer the original request.
The answer by Shikari is good for manual calculations. I'll also note the presence of a method getProcessCpuLoadBetweenTicks()
on the OSProcess
object starting in version 5.x that will do the CPU calculation for you.
Previous answer below:
I am the one who implemented the OSProcess class in OSHI that you are referencing, and have been communicating with you in an Issue on that project.
While OSHI does not currently provide all the functionality in the OSProcess
interface, it does provide you access methods to the WMI classes which will provide you all the information you seek. If you take a look at the WindowsOperatingSystem class which implements the getProcess()
method you're using, you can copy/modify the code using WMIUtil
to directly fetch the bits of information that you need.
OSHI currently fetches from the Win32_Process WMI class but as I've mentioned on the issue, it might be better to get information instead from Win32_PerfRawData_PerfProc_Process (which provides the raw data you can use for direct calculations) or Win32_PerfFormattedData_PerfProc_Process. In these classes you can find:
CPU usage
(Note while the name says "Percent" the raw data actually includes incrementing "ticks")
Memory usage
Disk usage, Network usage
In these classes, both Disk and Network are combined in the totals. (Again, for the "raw data" ignore the "per sec" part, it will give increasing total amounts of data).
I do not think Windows keeps track of the difference in Disk vs. Network IO on a per-process basis.
Steps you should take:
Define a comma-separated string with the WMI field names you want
Define a ValueType
array with types matching the field names, in
the same order
Execute Map<String, List<Object>> procs = WmiUtil.selectObjectsFrom(null, "Win32_PerfRawData_PerfProc_Process", processProperties, String.format("WHERE IdProcess=%d", pid), processPropertyTypes);
Fetch each value you want using procs.get("FieldNameHere").get(0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With