|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 2 of 2
Getting back to Java, loading the native library (silib.dll on Win32) is best accomplished via the static initializer in the SystemInformation class:
private static final String SILIB = "silib";
static
{
try
{
System.loadLibrary (SILIB);
}
catch (UnsatisfiedLinkError e)
{
System.out.println ("native lib '" + SILIB + "' not found in 'java.library.path': "
+ System.getProperty ("java.library.path"));
throw e; // re-throw
}
}
Note that getProcessCPUTime() returns CPU time used since the creation of the JVM process. By itself, this data is not particularly useful for profiling.
I need more utility Java methods to record data snapshots at various times and report CPU usage between any two time points:
public static final class CPUUsageSnapshot
{
private CPUUsageSnapshot (long time, long CPUTime)
{
m_time = time;
m_CPUTime = CPUTime;
}
public final long m_time, m_CPUTime;
} // end of nested class
public static CPUUsageSnapshot makeCPUUsageSnapshot ()
{
return new CPUUsageSnapshot (System.currentTimeMillis (), getProcessCPUTime ());
}
public static double getProcessCPUUsage (CPUUsageSnapshot start, CPUUsageSnapshot end)
{
return ((double)(end.m_CPUTime - start.m_CPUTime)) / (end.m_time - start.m_time);
}
The "CPU monitor API" is nearly ready for use! As a final touch, I create a singleton thread class, CPUUsageThread, which automatically takes data snapshots at regular intervals (0.5 seconds by default) and reports them to a set of CPU
usage event listeners (the familiar Observer pattern). The CPUmon class is a demo listener that simply prints the CPU usage to System.out:
public static void main (String [] args) throws Exception
{
if (args.length == 0)
throw new IllegalArgumentException ("usage: CPUmon <app_main_class> <app_main_args...>");
CPUUsageThread monitor = CPUUsageThread.getCPUThreadUsageThread ();
CPUmon _this = new CPUmon ();
Class app = Class.forName (args [0]);
Method appmain = app.getMethod ("main", new Class [] {String[].class});
String [] appargs = new String [args.length - 1];
System.arraycopy (args, 1, appargs, 0, appargs.length);
monitor.addUsageEventListener (_this);
monitor.start ();
appmain.invoke (null, new Object [] {appargs});
}
Additionally, CPUmon.main() "wraps" another Java main class with the sole purpose of starting CPUUsageThread before launching the original application.
As a demonstration, I ran CPUmon with the SwingSet2 Swing demo from JDK 1.3.1 (don't forget to install silib.dll into a location covered by either the PATH OS environment variable or the java.library.path Java property):
>java -Djava.library.path=. -cp silib.jar;(my JDK install dir)\demo\jfc\SwingSet2\SwingSet2.jar CPUmon SwingSet2 [PID: 339] CPU usage: 46.8% [PID: 339] CPU usage: 51.4% [PID: 339] CPU usage: 54.8% (while loading, the demo uses nearly 100% of one of the two CPUs on my machine) ... [PID: 339] CPU usage: 46.8% [PID: 339] CPU usage: 0% [PID: 339] CPU usage: 0% (the demo finished loading all of its panels and is mostly idle) ... [PID: 339] CPU usage: 100% [PID: 339] CPU usage: 98.4% [PID: 339] CPU usage: 97% (I switched to the ColorChooserDemo panel which ran a CPU-intensive animation that used both of my CPUs) ... [PID: 339] CPU usage: 81.4% [PID: 339] CPU usage: 50% [PID: 339] CPU usage: 50% (I used Windows NT Task Manager to adjust the CPU affinity for the "java" process to use a single CPU) ...
Of course, I can watch the same usage numbers via the task manager, but the point here is that I now have a programmatic way to record the same data. It will come in handy for long-running tests and server application diagnostics. The complete library (available in Resources) adds a few other useful native methods, including one for getting the process PID (for integration with external tools).