Allow invoker units to specify their own long threshold. Do away with the

invoker-wide long threshold configuration.


git-svn-id: https://samskivert.googlecode.com/svn/trunk@2133 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
mdb
2007-07-18 18:29:01 +00:00
parent 4747fa8f68
commit 3cd3397ad3
+54 -69
View File
@@ -26,31 +26,27 @@ import java.util.Iterator;
import com.samskivert.Log; import com.samskivert.Log;
/** /**
* The invoker is used to invoke self-contained units of code on an * The invoker is used to invoke self-contained units of code on an invoking thread. Each invoker
* invoking thread. Each invoker is associated with its own thread and * is associated with its own thread and that thread is used to invoke all of the units posted to
* that thread is used to invoke all of the units posted to that invoker * that invoker in the order in which they were posted. The invoker also provides a convenient
* in the order in which they were posted. The invoker also provides a * mechanism for processing the result of an invocation back on the main thread.
* convenient mechanism for processing the result of an invocation back on
* the main thread.
* *
* <p> The invoker is a useful tool for services that need to block and * <p> The invoker is a useful tool for services that need to block and therefore cannot be run on
* therefore cannot be run on the main thread. For example, an interactive * the main thread. For example, an interactive application might provide an invoker on which to
* application might provide an invoker on which to run database queries. * run database queries.
* *
* <p> Bear in mind that each invoker instance runs units on its own * <p> Bear in mind that each invoker instance runs units on its own thread and care must be taken
* thread and care must be taken to ensure that code running on separate * to ensure that code running on separate invokers properly synchronizes access to shared
* invokers properly synchronizes access to shared information. Where * information. Where possible, complete isolation of the services provided by a particular invoker
* possible, complete isolation of the services provided by a particular * is desirable.
* invoker is desirable.
*/ */
public class Invoker extends LoopingThread public class Invoker extends LoopingThread
implements RunQueue implements RunQueue
{ {
/** /**
* The unit encapsulates a unit of executable code that will be run on * The unit encapsulates a unit of executable code that will be run on the invoker thread. It
* the invoker thread. It also provides facilities for additional code * also provides facilities for additional code to be run on the main thread once the primary
* to be run on the main thread once the primary code has completed on * code has completed on the invoker thread.
* the invoker thread.
*/ */
public static abstract class Unit implements Runnable public static abstract class Unit implements Runnable
{ {
@@ -63,45 +59,51 @@ public class Invoker extends LoopingThread
this("Unknown"); this("Unknown");
} }
/** Creates an invoker unit which will report the supplied name in /** Creates an invoker unit which will report the supplied name in {@link #toString}. */
* {@link #toString}. */
public Unit (String name) public Unit (String name)
{ {
_name = name; _name = name;
} }
/** /**
* This method is called on the invoker thread and should be used * This method is called on the invoker thread and should be used to perform the primary
* to perform the primary function of the unit. It can return true * function of the unit. It can return true to cause the {@link #handleResult} method to be
* to cause the <code>handleResult</code> method to be * subsequently invoked on the dobjmgr thread (generally to allow the results of the
* subsequently invoked on the dobjmgr thread (generally to allow * invocation to be acted upon back in the context of the regular world) or false to
* the results of the invocation to be acted upon back in the * indicate that no further processing should be performed.
* context of the regular world) or false to indicate that no
* further processing should be performed.
* *
* @return true if the <code>handleResult</code> method should be * @return true if the {@link #handleResult} method should be called on the main thread,
* invoked on the main thread, false if not. * false if not.
*/ */
public abstract boolean invoke (); public abstract boolean invoke ();
/** /**
* Invocation unit implementations can implement this function to * Invocation unit implementations can implement this function to perform any post unit
* perform any post-unit-invocation processing back on the main * invocation processing back on the main thread. It will be invoked if {@link #invoke}
* thread. It will be invoked if <code>invoke</code> returns true. * returns true.
*/ */
public void handleResult () public void handleResult ()
{ {
// do nothing by default // do nothing by default
} }
// we want to be a runnable to make the receiver interface simple, // we want to be a runnable to make the receiver interface simple, but we'd like for
// but we'd like for invocation unit implementations to be able to // invocation unit implementations to be able to put their result handling code into an
// put their result handling code into an aptly named method // aptly named method
public void run () public void run ()
{ {
handleResult(); handleResult();
} }
/**
* Returns the duration beyond which this invoker unit will be considered to be running too
* long and result in a warning being logged. The default is 500ms.
*/
public long getLongThreshold ()
{
return DEFAULT_LONG_THRESHOLD;
}
/** Returns the name of this invoker. */ /** Returns the name of this invoker. */
public String toString () public String toString ()
{ {
@@ -112,8 +114,7 @@ public class Invoker extends LoopingThread
} }
/** /**
* Creates an invoker that will post results to the supplied result * Creates an invoker that will post results to the supplied result receiver.
* receiver.
*/ */
public Invoker (String name, RunQueue resultReceiver) public Invoker (String name, RunQueue resultReceiver)
{ {
@@ -122,18 +123,7 @@ public class Invoker extends LoopingThread
} }
/** /**
* Configures the duration after which an invoker unit will be considered * Posts a unit to this invoker for subsequent invocation on the invoker's thread.
* "long". When they complete, long units have a warning message
* logged. The default long threshold is 500 milliseconds.
*/
public void setLongThresholds (long longThreshold)
{
_longThreshold = longThreshold;
}
/**
* Posts a unit to this invoker for subsequent invocation on the
* invoker's thread.
*/ */
public void postUnit (Unit unit) public void postUnit (Unit unit)
{ {
@@ -184,8 +174,7 @@ public class Invoker extends LoopingThread
try { try {
willInvokeUnit(unit, start); willInvokeUnit(unit, start);
if (unit.invoke()) { if (unit.invoke()) {
// if it returned true, we post it to the receiver thread // if it returned true, post it to the receiver thread for result processing
// to invoke the result processing
_receiver.postRunnable(unit); _receiver.postRunnable(unit);
} }
didInvokeUnit(unit, start); didInvokeUnit(unit, start);
@@ -197,8 +186,8 @@ public class Invoker extends LoopingThread
} }
/** /**
* Shuts down the invoker thread by queueing up a unit that will cause * Shuts down the invoker thread by queueing up a unit that will cause the thread to exit after
* the thread to exit after all currently queued units are processed. * all currently queued units are processed.
*/ */
public void shutdown () public void shutdown ()
{ {
@@ -214,8 +203,8 @@ public class Invoker extends LoopingThread
* Called before we process an invoker unit. * Called before we process an invoker unit.
* *
* @param unit the unit about to be invoked. * @param unit the unit about to be invoked.
* @param start a timestamp recorded immediately before invocation if * @param start a timestamp recorded immediately before invocation if {@link #PERF_TRACK} is
* {@link #PERF_TRACK} is enabled, 0L otherwise. * enabled, 0L otherwise.
*/ */
protected void willInvokeUnit (Unit unit, long start) protected void willInvokeUnit (Unit unit, long start)
{ {
@@ -225,8 +214,8 @@ public class Invoker extends LoopingThread
* Called before we process an invoker unit. * Called before we process an invoker unit.
* *
* @param unit the unit about to be invoked. * @param unit the unit about to be invoked.
* @param start a timestamp recorded immediately before invocation if * @param start a timestamp recorded immediately before invocation if {@link #PERF_TRACK} is
* {@link #PERF_TRACK} is enabled, 0L otherwise. * enabled, 0L otherwise.
*/ */
protected void didInvokeUnit (Unit unit, long start) protected void didInvokeUnit (Unit unit, long start)
{ {
@@ -237,11 +226,10 @@ public class Invoker extends LoopingThread
recordMetrics(key, duration); recordMetrics(key, duration);
// report long runners // report long runners
if (duration > _longThreshold) { if (duration > unit.getLongThreshold()) {
String howLong = (duration >= 10*_longThreshold) ? String howLong = (duration >= 10*unit.getLongThreshold()) ? "Really long" : "Long";
"Really long" : "Long"; Log.warning(howLong + " invoker unit [unit=" + unit + " (" + key +
Log.warning(howLong + " invoker unit [unit=" + unit + "), time=" + duration + "ms].");
" (" + key + "), time=" + duration + "ms].");
} }
} }
} }
@@ -270,8 +258,7 @@ public class Invoker extends LoopingThread
public String toString () { public String toString () {
int count = _histo.size(); int count = _histo.size();
return _totalElapsed + "ms/" + count + " = " + return _totalElapsed + "ms/" + count + " = " + (_totalElapsed/count) + "ms avg " +
(_totalElapsed/count) + "ms avg " +
StringUtil.toString(_histo.getBuckets()); StringUtil.toString(_histo.getBuckets());
} }
@@ -287,15 +274,13 @@ public class Invoker extends LoopingThread
protected RunQueue _receiver; protected RunQueue _receiver;
/** Tracks the counts of invocations by unit's class. */ /** Tracks the counts of invocations by unit's class. */
protected HashMap<Object,UnitProfile> _tracker = protected HashMap<Object,UnitProfile> _tracker = new HashMap<Object,UnitProfile>();
new HashMap<Object,UnitProfile>();
/** The total number of invoker units run since the last report. */ /** The total number of invoker units run since the last report. */
protected int _unitsRun; protected int _unitsRun;
/** The duration of time after which we consider a unit to be delinquent /** The duration of time after which we consider a unit to be delinquent and log a warning. */
* and log a warning. */ protected static final long DEFAULT_LONG_THRESHOLD = 500L;
protected long _longThreshold = 500L;
/** Whether or not to track invoker unit performance. */ /** Whether or not to track invoker unit performance. */
protected static final boolean PERF_TRACK = true; protected static final boolean PERF_TRACK = true;