package com.bigdata.counters.osx; import java.util.UUID; import com.bigdata.counters.AbstractStatisticsCollector; import com.bigdata.counters.CounterSet; import com.bigdata.counters.IHostCounters; import com.bigdata.counters.IRequiredHostCounters; import com.bigdata.counters.PIDUtil; /** * Collection of host performance data using OSX native utilities (curent * vm_stat and iostat). * <p> * Note: Unfortunately, the OSX command line reporting utilities do NOT provide * access to IO Wait and do NOT break down IO into reads and writes. This means * that we can not provide reporting for the following counters: * <ul> * <li> {@link IRequiredHostCounters#PhysicalDisk_BytesReadPerSec}</li> * <li> {@link IRequiredHostCounters#PhysicalDisk_BytesWrittenPerSec}</li> * <li> {@link IHostCounters#CPU_PercentIOWait}</li> * </ul> * However, we are collecting the following which may be substituted to some * extent: * <ul> * <li> {@link IHostCounters#PhysicalDisk_BytesPerSec}</li> * <li> {@link IHostCounters#PhysicalDisk_TransfersPerSec}</li> * </ul> * However, there is no substitute for IO Wait. * * @see https://sourceforge.net/apps/trac/bigdata/ticket/225 * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id: StatisticsCollectorForLinux.java 4290 2011-03-11 15:12:26Z * thompsonbry $ */ public class StatisticsCollectorForOSX extends AbstractStatisticsCollector { /** * The process identifier for this process (the JVM). */ static protected int pid; static { pid = PIDUtil.getLinuxPIDWithBash(); } // /** // * The Linux {@link KernelVersion}. // */ // static protected KernelVersion kernelVersion; // static { // // kernelVersion = KernelVersion.get(); // // } // /** // * The name of the process (or more typically its service {@link UUID}) // * whose per-process performance counters are to be collected. // */ // private final String processName; /** * Reports on the host disk and CPU utilization (but not IOWait and does not * break out disk read versus write activity). */ private IOStatCollector iostat; /** * <code>vm_stat</code> reports on the host page faults, buffers, etc., but * it does NOT report on either CPU stats or IO Wait. */ private VMStatCollector vmstat; /** * TODO Under OSX, <code>top</code> provides more full featured reporting of * OS performance counters, including some IO counters and process specific * counters. Unfortunately, it does NOT provide IO Wait and it does NOT * break out IO by reads and writes. It is also more work to parse its * output. * <p> * <code>-l 0</code> turns on "logging" mode. The ZERO (0) indicates * infinite samples, rather than some finite number of samples. * <p> * <code>-s [delay]</code> sets the delay between reports. * <p> * <code>-S</code> adds reporting on swap space into the headers. * * <pre> * Swap: 545M + 479M free. * Purgeable: 31M 21336(0) pages purged. * </pre> * * Here is an example where the pid is NOT specified. * * <pre> * top -l 0 -s 60 -S * Processes: 107 total, 3 running, 104 sleeping, 587 threads * 2011/07/13 20:17:36 * Load Avg: 2.24, 1.77, 1.53 * CPU usage: 63.15% user, 36.84% sys, 0.0% idle * SharedLibs: 5292K resident, 6092K data, 0B linkedit. * MemRegions: 18245 total, 4813M resident, 30M private, 429M shared. * PhysMem: 1027M wired, 5472M active, 671M inactive, 7171M used, 1019M free. * VM: 263G vsize, 1042M framework vsize, 2911706(0) pageins, 2092534(0) pageouts. * Swap: 545M + 479M free. * Purgeable: 31M 21336(0) pages purged. * Networks: packets: 20768691/24G in, 22255115/23G out. * Disks: 3335765/133G read, 8511536/2051G written. * * PID COMMAND %CPU TIME #TH #WQ #PORTS #MREGS RPRVT RSHRD RSIZE VPRVT VSIZE PGRP PPID STATE UID FAULTS COW MSGSENT MSGRECV SYSBSD SYSMACH CSW PAGEINS USER * 94188 mdworker 0.0 00:06.04 3 1 48+ 60+ 836K+ 16M+ 2488K+ 31M+ 2408M+ 94188 1 sleeping 89 32402+ 147+ 115066+ 37438+ 263505+ 79593+ 55853+ 42+ _spotlight * 79486 Image Capture Ex 0.0 00:01.19 3 1 100+ 73+ 3052K+ 17M+ 7004K+ 40M+ 2672M+ 79486 865 sleeping 501 11662+ 174+ 126963+ 63971+ 26666+ 71795+ 16995+ 55+ bryan * 79438 Preview 0.0 00:31.59 3 1 207+ 453+ 30M+ 67M+ 65M+ 77M+ 2851M+ 79438 865 sleeping 501 96609+ 1466+ 330566+ 162122+ 709661+ 553728+ 129001+ 801+ bryan * 79114 TextEdit 0.0 00:04.80 3 2 121+ 193+ 6616K+ 28M+ 18M+ 44M+ 2751M+ 79114 865 sleeping 501 24588+ 870+ 211100+ 104015+ 52253+ 142782+ 43400+ 238+ bryan * 66520- Skype 0.0 89:18.16 21 2 538+ 658+ 161M+ 78M+ 208M+ 270M+ 1266M+ 66520 865 sleeping 501 115403971+ 2498+ 12493857+ 6119421+ 10995806+ 28285072+ 17521056+ 3683+ bryan * </pre> * * Top can be used to go after per-process statistics by specifying * <code>-pid [pid]</code>. It is also possible to request all processes * owned by a user with <code>-user [user]</code>. Here is an example where * the pid is specified. * * <pre> * top -l 0 -s 60 -S -pid 26866 * Processes: 107 total, 3 running, 104 sleeping, 649 threads * 2011/07/13 20:19:29 * Load Avg: 1.14, 1.49, 1.45 * CPU usage: 56.25% user, 43.75% sys, 0.0% idle * SharedLibs: 5292K resident, 6060K data, 0B linkedit. * MemRegions: 18439 total, 4806M resident, 30M private, 404M shared. * PhysMem: 969M wired, 4768M active, 1366M inactive, 7102M used, 1089M free. * VM: 263G vsize, 1042M framework vsize, 2911717(0) pageins, 2092534(0) pageouts. * Swap: 545M + 479M free. * Purgeable: 380K 22126(0) pages purged. * Networks: packets: 20876610/24G in, 22362893/23G out. * Disks: 3336157/133G read, 8512107/2051G written. * * PID COMMAND %CPU TIME #TH #WQ #PORTS #MREGS RPRVT RSHRD RSIZE VPRVT VSIZE PGRP PPID STATE UID FAULTS COW MSGSENT MSGRECV SYSBSD SYSMACH CSW PAGEINS USER * 26866 java 0.0 20:29.90 137/1 1 5890+ 703+ 2823M+ 7944K+ 2863M+ 3281M+ 7450M+ 21051 21052 running 501 1975814+ 2352+ 9530469+ 138939+ 5625664+ 25326440+ 10828748+ 8030+ bryan * </pre> * */ // private TOPCollector pidstat; public void start() { if (log.isInfoEnabled()) log.info("starting collectors"); super.start(); if (iostat != null) try { iostat.start(); } catch (Throwable t) { log.error(t, t); } if (vmstat != null) try { vmstat.start(); } catch (Throwable t) { log.error(t, t); } // if (pidstat != null) // try { // pidstat.start(); // } catch (Throwable t) { // log.error(t, t); // } } public void stop() { if (log.isInfoEnabled()) log.info("stopping collectors"); super.stop(); if (iostat != null) try { iostat.stop(); } catch (Throwable t) { log.error(t, t); } if (vmstat != null) try { vmstat.stop(); } catch (Throwable t) { log.error(t, t); } // if (pidstat != null) // try { // pidstat.stop(); // } catch (Throwable t) { // log.error(t, t); // } } @Override public CounterSet getCounters() { final CounterSet root = super.getCounters(); if (iostat != null) { /* * These are per-host counters. We attach them under the fully * qualified hostname. */ root.makePath(fullyQualifiedHostName).attach(iostat.getCounters()); } if (vmstat != null) { /* * These are per-host counters. We attach them under the fully * qualified hostname. */ root.makePath(fullyQualifiedHostName).attach(vmstat.getCounters()); } // if (pidstat != null) { // // /* // * These are per-process counters. We attach them under a path // * described by the fully qualified hostname followed by the process // * name. // */ // // root.makePath(fullyQualifiedHostName + ps + processName) // .attach(pidstat.getCounters()); // // } return root; } /** * * @param interval * The interval at which the performance counters will be * collected in seconds. * @param processName * The name of the process (or more typically its service * {@link UUID}) whose per-process performance counters are to * be collected. */ public StatisticsCollectorForOSX(final int interval, final String processName) { super(interval, processName); // if (processName == null) // throw new IllegalArgumentException(); // // this.processName = processName; // host wide collection iostat = new IOStatCollector(interval, true/* cpuStats */); // Enable supported collectors. vmstat = new VMStatCollector(interval); // // process specific collection. // pidstat = new PIDStatCollector(pid, interval, kernelVersion); } }