# HG changeset patch # User Dominic Cleal # Date 1281002845 -3600 # Node ID 6f68e94c1fb8af95acd282d59eab67f09f6f65c8 # Parent 0b92653586177f29b52fc5341239e902270cfaaf Add CondensedStats monitoring utility, equivalent to vmstat diff -r 0b9265358617 -r 6f68e94c1fb8 src/org/dancres/blitz/stats/IOStat.java --- a/src/org/dancres/blitz/stats/IOStat.java Sat Jun 12 10:52:10 2010 +0100 +++ b/src/org/dancres/blitz/stats/IOStat.java Thu Aug 05 11:07:25 2010 +0100 @@ -46,6 +46,10 @@ return theQueueSize; } + public int getThrottleCount() { + return theThrottleCount; + } + public String toString() { return "IO TPI: " + theTimePerIn + " TPO: " + theTimePerOut + " IOR: " + theInOutRatio + " QSZ: " + theQueueSize + " THROTTLE: " + diff -r 0b9265358617 -r 6f68e94c1fb8 src/org/dancres/blitz/stats/TaskQueueStat.java --- a/src/org/dancres/blitz/stats/TaskQueueStat.java Sat Jun 12 10:52:10 2010 +0100 +++ b/src/org/dancres/blitz/stats/TaskQueueStat.java Thu Aug 05 11:07:25 2010 +0100 @@ -17,6 +17,14 @@ return _id; } + public String getQueueName() { + return _queueName; + } + + public int getQueueSize() { + return _size; + } + public String toString() { return "Queue: " + _queueName + " size: " + _size; } diff -r 0b9265358617 -r 6f68e94c1fb8 src/org/dancres/blitz/stats/ThreadStat.java --- a/src/org/dancres/blitz/stats/ThreadStat.java Sat Jun 12 10:52:10 2010 +0100 +++ b/src/org/dancres/blitz/stats/ThreadStat.java Thu Aug 05 11:07:25 2010 +0100 @@ -33,6 +33,10 @@ return new ThreadStat(theId, myActiveCount); } + public int getThreadCount() { + return theThreadCount; + } + public String toString() { return "Thread count: " + theThreadCount; } diff -r 0b9265358617 -r 6f68e94c1fb8 src/org/dancres/blitz/tools/CondensedStats.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/dancres/blitz/tools/CondensedStats.java Thu Aug 05 11:07:25 2010 +0100 @@ -0,0 +1,251 @@ +package org.dancres.blitz.tools; + +import java.io.PrintStream; +import java.rmi.RemoteException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Formatter; + +import org.dancres.blitz.remote.StatsAdmin; +import org.dancres.blitz.stats.BlockingOpsStat; +import org.dancres.blitz.stats.EventQueueStat; +import org.dancres.blitz.stats.IOStat; +import org.dancres.blitz.stats.InstanceCount; +import org.dancres.blitz.stats.MemoryStat; +import org.dancres.blitz.stats.MissedOpsStat; +import org.dancres.blitz.stats.OpStat; +import org.dancres.blitz.stats.Stat; +import org.dancres.blitz.stats.TaskQueueStat; +import org.dancres.blitz.stats.ThreadStat; +import org.dancres.blitz.stats.TxnStat; + +/** +

CondensedStats accepts a spacename as an argument and a loop time. It + then regularly prints a condensed view of some important space stats every + loop time seconds. Specifying a loop time of 0 will cause MonitorStats to + dump stats once and exit.

+ +

Typical usage: + +

+   java -Xmx256m -Djava.security.policy=config/policy.all
+     -classpath /home/dan/jini/jini2_0/lib/jsk-platform.jar:/home/dan/src/jini/space/build:/home/dan/jini/jini2_0/lib/jini-ext.jar:/home/dan/jini/jini2_0/lib/sun-util.jar
+     org.dancres.blitz.tools.CondensedStats dancres 20
+   
+ + @see org.dancres.blitz.remote.BlitzAdmin + */ +public class CondensedStats extends MonitorStats { + public static void main(String args[]) { + new CondensedStats().startup(args); + } + + @Override + Runnable getWatcher(StatsAdmin anAdmin, long aTimeout) + { + return new CondensedWatcher(anAdmin, aTimeout); + } + + /** + * Provides a vmstat-style one line repeating summary of Blitz statistics. + * Includes operation counts, active txns/ops, listeners and queue stats, + * writer I/O and VM stats. + */ + static class CondensedWatcher implements Runnable { + private StatsAdmin theAdmin; + private long theTimeout; + private Stat[] theLastStats; + + CondensedWatcher(StatsAdmin anAdmin, long aTimeout) { + theAdmin = anAdmin; + theTimeout = aTimeout; + } + + public void run() { + boolean run = true; + while (run) { + try { + // if timeout is 0, run once over a 1 second period + if (theTimeout == 0) { + run = false; + theTimeout = 1000; + } + + printHeader(System.out); + + theLastStats = theAdmin.getStats(); + + for (int i = 0;; i++) { + Thread.sleep(theTimeout); + + print(System.out, (int)theTimeout / 1000); + if ((i + 1) % 48 == 0) + printHeader(System.out); + } + } catch (Exception anE) { + System.err.println(anE); + anE.printStackTrace(); + } + } + } + + public void printHeader(PrintStream out) { + out.println("-----ops---- " + + " missed " + + "obj " + + "---active-- " + + "listeners " + + "---queues-- " + + "------io----- " + + "-----vm-----"); + + out.println(" r t w " + + " r t " + + "+/- " + + "txn r t " + + " tr pt " + + "evt rem oth " + + " i/o qsz thr " + + "thrd mem max"); + } + + public void print(PrintStream out, int interval) throws RemoteException { + Stat[] last = theLastStats; + Stat[] stats = theAdmin.getStats(); + + // Operation count since last iteration + long opReads = getOpCount(stats, OpStat.READS) - + getOpCount(last, OpStat.READS); + long opTakes = getOpCount(stats, OpStat.TAKES) - + getOpCount(last, OpStat.TAKES); + long opWrites = (getOpCount(stats, OpStat.WRITES) - + getOpCount(last, OpStat.WRITES)) / interval; + + // Missed operations, not available until first operation + long missReads = 0, missTakes = 0; + MissedOpsStat missedStat = getStatistic(stats, MissedOpsStat.class); + MissedOpsStat missedLast = getStatistic(stats, MissedOpsStat.class); + + if (missedStat != null && missedLast != null) { + missReads = (missedStat.getMissedReads() - missedLast.getMissedReads()) + / interval; + missTakes = (missedStat.getMissedTakes() - missedLast.getMissedTakes()) + / interval; + } + + // Change op counts to include misses + opReads = (opReads + missReads) / interval; + opTakes = (opTakes + missTakes) / interval; + + // Overall instance count + long instances = (getInstanceCount(stats) - getInstanceCount(last)) + / interval; + + // Active operations/txns + int activeTxn = getStatistic(stats, TxnStat.class).getActiveTxnCount(); + + // Not available until after first space operation + int activeRead = 0, activeTake = 0; + BlockingOpsStat blockedOps = getStatistic(stats, BlockingOpsStat.class); + if (blockedOps != null) { + activeRead = blockedOps.getReaders(); + activeTake = blockedOps.getTakers(); + } + + // Notify listeners + int listenTrans = getStatistic(stats, EventQueueStat.class).getTransientCount(); + int listenPers = getStatistic(stats, EventQueueStat.class).getPersistentCount(); + + // Queues, internal notify queue, remote notify queue and other tasks + int queueEvents = getTaskQueue(stats, "Events"); + int queueRemote = getTaskQueue(stats, "RemoteEvent"); + int queueOther = getTaskQueue(stats, "DefaultTask"); + + // Writer I/O if persistent storage model in use + double ioRatio = 0; + int ioQueueSize = 0, ioThrottle = 0; + + IOStat myIoStat = getStatistic(stats, IOStat.class); + if (myIoStat != null) { + ioRatio = myIoStat.getInOutRatio(); + ioQueueSize = getStatistic(stats, IOStat.class).getQueueSize(); + ioThrottle = (getStatistic(stats, IOStat.class).getThrottleCount() - + getStatistic(last, IOStat.class).getThrottleCount()) + / interval; + } + + // Virtual machine + int vmThreads = getStatistic(stats, ThreadStat.class).getThreadCount(); + + double vmMemory = getStatistic(stats, MemoryStat.class).getCurrentMemory(); + vmMemory = vmMemory / 1024 / 1024 / 1024; + + double vmMaxMem = getStatistic(stats, MemoryStat.class).getMaxMemory(); + vmMaxMem = vmMaxMem / 1024 / 1024 / 1024; + + // r t w$ r w$ +/-$txn r t$ tr pt + String formatString = "%4d %3d %3d %4d %3d %5d %4d %3d %3d %5d %4d "; + // evt rem oth$i/o qsz thr$thrd mem max + formatString += "%4d %3d %3d %5.1f %4d %3d %5d %3.1f %3.1f"; + + String line = new Formatter().format(formatString, + opReads, opTakes, opWrites, + missReads, missTakes, instances, + activeTxn, activeRead, activeTake, + listenTrans, listenPers, + queueEvents, queueRemote, queueOther, + ioRatio, ioQueueSize, ioThrottle, + vmThreads, vmMemory, vmMaxMem).toString(); + + out.println(line); + + theLastStats = stats; + } + + private Collection getStatistics(Stat[] allStats, + Class statClazz) { + Collection ret = new ArrayList(); + for (Stat stat : allStats) + if (statClazz.isInstance(stat)) + ret.add(statClazz.cast(stat)); + + return ret; + } + + private T getStatistic(Stat[] allStats, + Class statClazz) { + Collection subset = getStatistics(allStats, statClazz); + return (subset.isEmpty()) ? null : subset.iterator().next(); + } + + /** Adds up operations across all entry types. + * @param opType OpStat.TAKES/READS/WRITES + */ + private long getOpCount(Stat[] stats, int opType) { + long count = 0; + for (OpStat ops : getStatistics(stats, OpStat.class)) + if (ops.getOp() == opType) + count += ops.getCount(); + + return count; + } + + /** Adds up instance counts across all entry types. */ + private long getInstanceCount(Stat[] stats) { + long count = 0; + for (InstanceCount ops : getStatistics(stats, InstanceCount.class)) + count += ops.getCount(); + + return count; + } + + /** Gets size of a task queue with a particular task name */ + private int getTaskQueue(Stat[] stats, String taskName) { + for (TaskQueueStat ops : getStatistics(stats, TaskQueueStat.class)) + if (taskName.equals(ops.getQueueName())) + return ops.getQueueSize(); + + return 0; + } + } +} diff -r 0b9265358617 -r 6f68e94c1fb8 src/org/dancres/blitz/tools/MonitorStats.java --- a/src/org/dancres/blitz/tools/MonitorStats.java Sat Jun 12 10:52:10 2010 +0100 +++ b/src/org/dancres/blitz/tools/MonitorStats.java Thu Aug 05 11:07:25 2010 +0100 @@ -1,35 +1,17 @@ package org.dancres.blitz.tools; import java.io.IOException; - +import java.rmi.RMISecurityManager; import java.rmi.RemoteException; -import java.rmi.RMISecurityManager; - -import net.jini.discovery.*; - -import net.jini.lookup.*; -import net.jini.lookup.entry.Name; - -import net.jini.core.lookup.ServiceItem; -import net.jini.core.lookup.ServiceTemplate; - -import net.jini.core.entry.Entry; import net.jini.admin.Administrable; - import net.jini.space.JavaSpace; -import net.jini.core.transaction.TransactionException; - -import org.dancres.blitz.remote.BlitzAdmin; - +import org.dancres.blitz.remote.StatsAdmin; +import org.dancres.blitz.stats.Stat; import org.dancres.jini.util.DiscoveryUtil; import org.dancres.jini.util.ServiceLocator; -import org.dancres.blitz.stats.*; - -import org.dancres.blitz.remote.StatsAdmin; - /**

MonitorStats accepts a spacename as an argument and a loop time. It then attempts to list all available statistics on the space every loop time @@ -50,6 +32,10 @@ private static final long MAX_DISCOVER_TIME = 15 * 1000; public static void main(String args[]) { + new MonitorStats().startup(args); + } + + void startup(String args[]) { if (System.getSecurityManager() == null) System.setSecurityManager(new RMISecurityManager()); @@ -93,20 +79,7 @@ StatsAdmin myStatsAdmin = (StatsAdmin) myAdminProxy; - if (myTimeout == 0) { - Stat[] myStats = myStatsAdmin.getStats(); - - System.out.println("Snapshot: " + - System.currentTimeMillis()); - for (int i = 0; i < myStats.length; i++) { - System.out.println(myStats[i]); - } - - System.out.println(); - - } else { - new Watcher(myStatsAdmin, myTimeout).start(); - } + getWatcher(myStatsAdmin, myTimeout).run(); } else { System.err.println("No BlitzAdmin interface found - can't be Blitz"); } @@ -129,7 +102,11 @@ } } - static class Watcher extends Thread { + Runnable getWatcher(StatsAdmin anAdmin, long aTimeout) { + return new Watcher(anAdmin, aTimeout); + } + + static class Watcher implements Runnable { private StatsAdmin theAdmin; private long theTimeout; @@ -139,7 +116,7 @@ } public void run() { - while (true) { + do { try { Stat[] myStats = theAdmin.getStats(); @@ -155,7 +132,7 @@ } catch (Exception anE) { System.err.println(anE); } - } + } while (theTimeout > 0); // if timeout == 0, only run once } } }