Take a Cue From Queues
New York City has an inexcusable population density, and its inhabitants are some of the most self-important existentialists on Earth.
We’ve all got something to do, it’s urgent, we need it accomplished now, and heaven help your sorry butt if you keep us waiting.
So the Service Industry has gotten pretty damn good at getting us our Iced Quad Nonfat Caramel Macchiatos, with Whip!, in due time.
There are some impressive retail strategies for dealing with the masses. I’ve seen:
- One queue feeding into many sales registers
- One queue per register
- One queue, with many associates performing specialized units of work; processing a transaction in phases
Selection of one over the others is generally dependent on the business rules governing the transaction. But there is a common denominator here: The Queue.
Traditionally called “lines” in the United States, the queue represents a holding pattern of service requests until resources become available. This guarantees an even thoroughput.
But hey, I’ve got a new idea! Waiting blows…so I’m going to remove the queue from this equation. Let’s see what happens.
- I arrive at the bank, noticing one teller who is dealing with a customer.
- I approach the counter and give the busy banker my deposit slip and checks.
- The teller alternates between the work she was doing prior to my arrival and the new task I’ve just given her, switching repeatedly.
- The existing customer gives me a dirty look; her work is now being performed at 1/2 speed.
- A new couple walks in, giving the teller 2 requests for a withdrawl.
- Work on Customer 1 is still not done, and is now being performed at 1/4 speed.
- Murder Scene
Maybe I need to rethink this. So its back to the lab, where I send all computational problems to Carlo de Wolf for analysis.
“The issue,” he explains, “is one of Resource Starvation.”
And the EJB3 lead of JBoss kindly continues to draw up reproducible test cases.
Let’s assume a stressing function, where we calculate Pi to 10000 digits 100 times. The idea here is just to get the CPU crunching to simulate some heavy processing.
We’ll invoke this once using traditional IoC/Dependency Injection, and again using EJB3 mechanics. Then we’ll compare the metrics.
// Make an IoC Container Instance
IocContainer ioc = new IocContainer();
// Install the Calculator class, bound to a key
ioc.install("calculator", CalculatorBean.class);
// Lookup an instance
Calculator calculator = ioc.lookup("calculator", Calculator.class);
// Run the Stressor and print metrics
StressCreator.createStress(calculator);
Neat. Pretty simple. We programatically register a class, grab an instance, and use that instance to churn out our results:
Total Time: 28.21 Seconds
Not Executing: 0.235 Seconds
Invocation Time: 27.814 Seconds
Allright. Because we don’t have a queue here, we spend very little time outside of actual invocation of the test, and the majority of time is spent processing Pi 100 times.
Let’s do another run, using the same Stressor, but using EJB.
// Make an EJB Container
EjbContainer ejbC = new EjbContainer();
// Deploy the EJB
ejbC.deploy(CalculatorBean.class);
// Lookup an EJB Instance
Calculator calculator = (Calculator) new InitialContext().lookup("CalculatorBean/remote");
// Run the Stressor and print metrics
StressCreator.createStress(calculator);
Wonder what we’ll get this time.
From The Caller’s View:
Took 27.691 Seconds
Not Executing: 0.035 Seconds
Invocation Time: 27.541 SecondsCollected From Inside the EJB Container:
Average Time Waiting on Queue: 13.37449 Seconds
Average Invocation Time: 1.3689 Seconds
From the point of view of a unified caller requesting 100 intensive service calls…looks pretty similar to IoC.
But there’s more here. We’ve now got a hook into the EJB Container, and can clearly see…average execution time of each of the 100 calls is about 1/100 the amount of time spent waiting on an available processor. WHY?
Because with EJB, you get instance pooling for free. When all available instances are taken from the pool, new invocations must queue up. And when you block incoming requests from slowing down your whole system, each individual request can be handled in a reasonable fashion.
The obvious question might be: What’s the damn difference? Both methods take nearly the same amount of time!
Sure. As fantastic as the EJB specification is, it can’t invent CPU cycles on the fly. What it CAN do is provide for incremental return. So the first requests in make it out without having to wait on everyone else in line to complete.
So I can easily draw the following conclusions, assuming 100 concurrent requests:
- At WORST, the last service request in EJB will return at the same time as the full IoC return.
- At BEST, EJB will begin to return requests in under 2 seconds, and these clients may be on their way.
- You will not have any N number of Threads spreading your processor too thin.
- If you’re allowing an Enterprise System to spawn a Thread for each request, you should work for McDonald’s.
On second thought, I revoke my last point. Even pre-teens working the McDonald’s drive-through make each car wait its turn.
S,
ALR

Hi, all!
ALR, good point! But… Actually I’am also a crazy ejb fan.. But..
This feature (thread pool) isn’t a specific ejb feature.. Any middleware solution has it i.e. Tomcat has thread pool for servlet calls. Also we can configure these for Spring remoting..
So, Your post it’s a great explanation about thread pool execution architecture pattern, But it isn’t a proof for ejb needs
crazyMike
crazyMike:
Yep, pooling (and in particular Thread pooling) has been a proven technique for years now. My post, however, addresses *business object instance* pooling to limit the number of Threads used. The EJB Core Spec in Section 4.7.11 defines that container implementations must not allow for re-entrant invocations; each instance must be serving at most one request (Thread) at any given time. The side effect of this is a request queue once no instances are available.
And sure, this isn’t specific to EJB - you can plug most any Enterprise feature into your existing infrastructure. My goal is to illustrate point-by-point that there’s no extraneous bloat in the specification, and that EJB provides the application developer with low-level utilities that are absolutely necessary.
S,
ALR
Ahhh, this post reminds me my naivity 6 years ago. And it was ejb 2.0 times! Now in times of ejb 3.0 most of developers wants singleton (see ejb 3.1 proposals) instead of useless object pooling from needed in JVM 1.1 times, when object creation was really expensive. Now I’d rather watch ejb camp amused from distance. It’s not worth the effort
Martin:
Please read the concerns I’m addressing through object pooling - not the overhead of instanciation, but gaining finer-grained control over how many Threads are pouring through your process at one time.
It’s a reach to say “most” developers want @Singleton in EJB 3.1, inferring that this would somehow be a default strategy. In many ways, this is analogous to JBoss’ @Service (which creates a Singleton JMX MBean), and I’ve found it useful in many cases. Take, for instance, a file transfer service which may send long byte arrays over the wire - I don’t want too many requests executing through here at once, and I might throttle it by having an MDB dispatch to a Singleton resource. I could alternatively specify an @Stateless to be backed by a Strict pool of low number, but this is implementation-specific.
Also note that with @Singleton comes a series of proposals to address method-level concurrency options, giving the developer even more flexibility within an easily-defined syntax.
S,
ALR
why, this feature is nice to have
could you please describe how to configure the pooling parameters for particular use cases?
Ivan:
Configuration of the SLSB Pool or SFSB Cache is implementation-specific. In JBoss, we use the @PoolConfig and @CacheConfig annotations (and XML equivalents in jboss.xml) to specify the backing impl and parameters.
Take a look at ejb3-interceptors-aop.xml for definitions of these annotations by default (when the developer has not added them explicitly).
S,
ALR