e77949a143
point Pulse can probably totally replace the ReportManager at which time a bunch of cruft can go away. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5757 542714f4-19e9-0310-aa3c-eee0fc999fb1
156 lines
5.7 KiB
Java
156 lines
5.7 KiB
Java
//
|
|
// $Id$
|
|
//
|
|
// Narya library - tools for developing networked games
|
|
// Copyright (C) 2002-2008 Three Rings Design, Inc., All Rights Reserved
|
|
// http://www.threerings.net/code/narya/
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it
|
|
// under the terms of the GNU Lesser General Public License as published
|
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
package com.threerings.presents.server;
|
|
|
|
import com.samskivert.util.Invoker;
|
|
import com.samskivert.util.RunQueue;
|
|
import com.samskivert.util.StringUtil;
|
|
|
|
/**
|
|
* Extends invoker with a reporter implementation that shows current queue status, maximum
|
|
* historical size and the results of unit profiling if enabled.
|
|
*/
|
|
public class ReportingInvoker extends Invoker
|
|
{
|
|
public static class Stats
|
|
{
|
|
public int unitsRun;
|
|
public int maxQueueSize;
|
|
}
|
|
|
|
/**
|
|
* Creates a new reporting invoker. The instance will be registered with the report manager
|
|
* if profiling is enabled ({@link Invoker#PERF_TRACK}).
|
|
*/
|
|
public ReportingInvoker (String name, RunQueue resultsQueue, ReportManager repmgr)
|
|
{
|
|
super(name, resultsQueue);
|
|
if (PERF_TRACK) {
|
|
repmgr.registerReporter(ReportManager.DEFAULT_TYPE, _defrep);
|
|
repmgr.registerReporter(ReportManager.PROFILE_TYPE, _profrep);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a recent snapshot of runtime statistics tracked by the invoker.
|
|
*
|
|
* @param snapshot if true, the current stats will be snapshotted and reset and the new
|
|
* snapshot will be returned. If false, the previous snapshot will be returned. If no snapshot
|
|
* has ever been taken, the current stats that have been accumulting since the JVM start will
|
|
* be returned.
|
|
*/
|
|
public Stats getStats (boolean snapshot)
|
|
{
|
|
synchronized (this) {
|
|
if (snapshot) {
|
|
_recent = _current;
|
|
_current = new Stats();
|
|
_current.maxQueueSize = _queue.size();
|
|
}
|
|
return _recent;
|
|
}
|
|
}
|
|
|
|
@Override // from Invoker
|
|
protected void willInvokeUnit (Unit unit, long start)
|
|
{
|
|
super.willInvokeUnit(unit, start);
|
|
|
|
int queueSize = _queue.size();
|
|
synchronized (this) {
|
|
// keep track of the largest queue size we've seen
|
|
if (queueSize > _current.maxQueueSize) {
|
|
_current.maxQueueSize = queueSize;
|
|
}
|
|
_current.unitsRun++;
|
|
|
|
// note the currently invoking unit
|
|
_currentUnit = unit;
|
|
_currentUnitStart = start;
|
|
}
|
|
}
|
|
|
|
@Override // from Invoker
|
|
protected void didInvokeUnit (Unit unit, long start)
|
|
{
|
|
super.didInvokeUnit(unit, start);
|
|
|
|
synchronized (this) {
|
|
// clear out our currently invoking unit
|
|
_currentUnit = null;
|
|
_currentUnitStart = 0L;
|
|
}
|
|
}
|
|
|
|
/** Generates a report on our runtime behavior. */
|
|
protected ReportManager.Reporter _defrep = new ReportManager.Reporter() {
|
|
public void appendReport (StringBuilder buf, long now, long sinceLast, boolean reset) {
|
|
buf.append("* " + getName() + ":\n");
|
|
int qsize = _queue.size();
|
|
buf.append("- Queue size: ").append(qsize).append("\n");
|
|
synchronized (this) {
|
|
Stats stats = getStats(reset);
|
|
buf.append("- Max queue size: ").append(stats.maxQueueSize).append("\n");
|
|
buf.append("- Units executed: ").append(stats.unitsRun);
|
|
long runPerSec = (sinceLast == 0) ? 0 : stats.unitsRun/(sinceLast/1000);
|
|
buf.append(" (").append(runPerSec).append("/s)\n");
|
|
if (_currentUnit != null) {
|
|
String uname = StringUtil.safeToString(_currentUnit);
|
|
buf.append("- Current unit: ").append(uname).append(" ");
|
|
buf.append(now-_currentUnitStart).append("ms\n");
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/** Generates a report with our profiling data. */
|
|
protected ReportManager.Reporter _profrep = new ReportManager.Reporter() {
|
|
public void appendReport (StringBuilder buf, long now, long sinceLast, boolean reset) {
|
|
buf.append("* " + getName() + ":\n");
|
|
if (PresentsDObjectMgr.UNIT_PROF_ENABLED) {
|
|
for (Object key : _tracker.keySet()) {
|
|
UnitProfile profile = _tracker.get(key);
|
|
if (key instanceof Class) {
|
|
key = StringUtil.shortClassName((Class<?>)key);
|
|
}
|
|
buf.append(" ").append(key).append(" ");
|
|
buf.append(profile).append("\n");
|
|
if (reset) {
|
|
profile.clear();
|
|
}
|
|
}
|
|
} else {
|
|
buf.append(" - Unit profiling disabled.\n");
|
|
}
|
|
}
|
|
};
|
|
|
|
/** Used to track runtime statistics. */
|
|
protected Stats _recent = new Stats(), _current = _recent;
|
|
|
|
/** Records the currently invoking unit. */
|
|
protected Object _currentUnit;
|
|
|
|
/** The time at which our current unit started. */
|
|
protected long _currentUnitStart;
|
|
}
|