Thread overhead

S

Simon Brooke

I'm developing an abstract monitoring framework which consists of a
(potentially) large number of simple agents each of which watches a single
thing, where these things change slowly and infrequently. My Watcher
objects sleep for periods typically from a few hours up to many days, wake
up, check the thing they're watching in a few seconds, and then if
everything's OK go to sleep again. In implementation terms it's incredibly
easy to do this by giving each Watcher a thread of its own:

/** a token to identify the sleep time in the configuration */
public static final String INTERVALTOKEN = "period";

/** how many milliseconds I sleep between periods of activity */
protected long winks = 5 * 60 * 1000;

/** my thread */
protected Thread thread = null;

/** the exceptions which occurred as I was watching */
protected Vector whinges = new Vector( );

/**
* initialise me with this configuration
*/
public void init( Map config ) throws AlertingException
{
....
Object val = config.get( INTERVALTOKEN );

if ( val == null )
{
val = config.get( "p" );
}

if ( val != null )
{
winks = (long) ( Integer.parseInt( val.toString( ) ) * 1000 );
}
...
}

/**
* perform a check to see whether the event I am watching for has
* occurred.
*
* @return a vector of maps each one of which represents an alert which
* should be sent. If no alerts should be sent, return an empty
* vector.
*/
protected abstract Vector check( ) throws Exception;


/**
* periodically wake up check the things I'm watching. If any have
* changed send appropriate alerts
*/
public void run( )
{
while ( thread != null )
{
if ( whinges.size( ) < TOOMANYERRORS)
{
try
{
Vector alerts = check( );

if ( alerts != null )
{
Enumeration e = alerts.elements( );

while ( e.hasMoreElements( ) )
{
Map context = (Map) e.nextElement( );

try
{
sendAlert( context );
mark( context );
}
catch ( Exception oops )
{
whinge( oops );
whinges.add( oops );
}
}
}
}
catch ( Exception whinge )
{
whinge( whinge );
whinges.add( whinge );
}
}
else
{ // stop the thread!
stop( );
}

try
{
Thread.sleep( winks );
}
catch ( InterruptedException wakeywakey )
{
break;
}
}
}

But what's bothering me is what this costs. It particularly bothers me
because, while at this stage in the development of my system I'm dealing
with a few tens of these objects, in the long term I could be dealing with
several hundreds.

Are threads essentially very lightweight things which allow this framework
to be efficient, or are they quite heavyweight and I'd be better working
on an architecture where a single thread wakes up periodically and polls
watchers for whether they want to run?

--
(e-mail address removed) (Simon Brooke) http://www.jasmine.org.uk/~simon/
Ye hypocrites! are these your pranks? To murder men and give God thanks?
Desist, for shame! Proceed no further: God won't accept your thanks for
murther
-- Robert Burns, 'Thanksgiving For a National Victory'
 
M

Matt Humphrey

Simon Brooke said:
I'm developing an abstract monitoring framework which consists of a
(potentially) large number of simple agents each of which watches a single
thing, where these things change slowly and infrequently. My Watcher
objects sleep for periods typically from a few hours up to many days, wake
up, check the thing they're watching in a few seconds, and then if
everything's OK go to sleep again. In implementation terms it's incredibly
easy to do this by giving each Watcher a thread of its own:

But what's bothering me is what this costs. It particularly bothers me
because, while at this stage in the development of my system I'm dealing
with a few tens of these objects, in the long term I could be dealing with
several hundreds.

Are threads essentially very lightweight things which allow this framework
to be efficient, or are they quite heavyweight and I'd be better working
on an architecture where a single thread wakes up periodically and polls
watchers for whether they want to run?

Threads are much lighter weight than processes, but they still have costs.
There are also limits to the number of available threads and there is
context-switching overhead. Using a simple thread-per-Watcher design at
this point could be wasteful, particularly when there are easy alternatives.

If your agents do exactly as you describe--wait for hours to days--all you
need is a scheduler that has a list of Watchers ordered by time of next
activation. A single thread monitors this list. If more than one Watcher
could activiate simultaneously, just use a thread for each of these or (even
better) a thread pool. A simple scheduler will also be easier to persist to
disk and reload when you have to restart your system.

Matt Humphrey (e-mail address removed) http://www.iviz.com/
 
H

hiwa

Matt may be right as a real-world design theory but, if the number of
the 'Watcher' is moderate for the memory occupancy, I'd prefer OP's
cookie-cutter multi-threading design because it is simple and carefree.
If you use wait/notify mechanism or
java.util.concurrent.locks.Condition objects from a driver/controller
instead of each thread using Thread.sleep(), waste of CPU usage would
not occur.
 
E

EJP

hiwa said:
Matt may be right as a real-world design theory but, if the number of
the 'Watcher' is moderate for the memory occupancy, I'd prefer OP's
cookie-cutter multi-threading design because it is simple and carefree.

.... except that he's explicitly worried about scalability, which is why
he posted.

I think he should have a look at java.util.Timer.
 
O

opalpa

Let me add a little to what Matt, hiwa, and EJB have stated:

EJB's suggestion to look into java.util.Timer is very good. Since you
find original design incredibly easy to do you may be suprised that
there is an easier way still.

Specific item to keep in mind: When your program grows to monitor a
hundred or two hundred things you may run into a file descriptor
shortage. This situation is from perosnal experience with having two
hundred threads each of which had an open socket. File descriptor
limits are system attributes, not Java's.

Thread weight varies greatly. In some environments threads are very
cheap, and incredibly fast. In some environment threads are more than
ten times more expensive (in terms of time to create and memory
needed). In some environments you can choose a model when starting a
VM. The available thread models have changed with jdk versions. It
may be prudent to look into thread models on the system and jdks you
use and will be using in the future. For example for Solaris you can
learn about your threading options at
http://java.sun.com/docs/hotspot/threads/threads.html . Google helps
alot in researching Java's threading models.

Last comment, I second hiwa's suggestion to look into wait/notify .
I'm not sure where you are in your Java experience. wait/notify are
not the simplest things to get comfortable with. But look, every
Object in java has wait/notify, it's as ubiqitous as equals, hashCode,
and toString .

All the best,
Opalinski
(e-mail address removed)
http://www.geocities.com/opalpaweb/
 
S

Simon Brooke

EJP said:
... except that he's explicitly worried about scalability, which is why
he posted.

I think he should have a look at java.util.Timer.

Thanks all. It needs thinking about, because you build something intending
it to be used for something fairly simple and before you know it some user
is stressing it in ways you hadn't predicted. I need it to be robust under
stress.
 
S

Simon Brooke

hiwa said:
What kind of things they could be?
Range of input values, f'instance?

The immediate application is a web content management system. Part of the
content it manages is links to foreign sites. As we know, there are
several kinds of link-rot out there. Content changes, which may or may not
be benign. Content gets deleted; and servers simply disappear, either
temporarily or permanently. To prevent showing stale links to users, we
monitor the links by sending periodic HEAD requests.

The administrator of the system can set up policies for blocks of links
stating how frequently they should be checked, and what to do if the
content changes and/or disappears.

However, as usual, I'm trying to keep things as general as possible, so I
built it using a system monitoring package I wrote a couple of years ago
http://www.weft.co.uk/library/jacquard/documentation/uk/co/weft/alert/package-summary.html

This works quite well for small numbers of Watcher agents. However many
years ago I wrote a content management system for the core of British
Telecom's intranet, which had stale link management for tens of thousands
of links. That was a special purpose application, and I don't expect my
current system (http://www.weft.co.uk/products/PRES/) to be used in that
way. But it could be, and it should not fail if it is.

Having given it some thought, I'm planning to write a new framework which
runs a single thread, waking up to handle any current checks and then
computing how long it can sleep before a new check of any watched resource
is due. This will need to be 'tickled' when new watched resources are
added, of course, so that it can recompute its remaining 'safe to sleep'
time.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top