One clerk hands out tools to two kinds of mechanic. Short requests jump the line. The model shows what that rule costs the people it sends to the back.
Mechanics come to a crib for tools. Class 1 mechanics arrive every 420 ± 360 seconds and keep the clerk busy for 300 ± 90. Class 2 mechanics arrive every 360 ± 240 seconds with quick requests of 100 ± 30. All the times are uniform over those ranges.
The clerk serves class 2 first. Nobody is interrupted: a class 1 request already under way is finished, but whenever the clerk frees up, a waiting class 2 mechanic goes ahead of every class 1 mechanic in line. The run is one eight-hour shift, 28,800 seconds.
Add up the averages and the clerk has 300/420 + 100/360 of an hour’s work in every hour, about 99%. The crib is close to full, and that is what makes the priority rule interesting.
In the deck, priority is the fifth field of GENERATE: ,,,1 and ,,,2. Each class has its own line so the statistics come out separately, and one SEIZE CLERK serves both, highest priority first.
chiaha-SLX says the same thing on the arrivals statement, priority = 2, and the clerk’s waiting line is kept in priority order. The rest of each mechanic’s actions are the deck’s blocks in the deck’s order.
GENERATE 420,360,,,1
QUEUE LINE1
SEIZE CLERK
DEPART LINE1
ADVANCE 300,90
RELEASE CLERK
TERMINATE
GENERATE 360,240,,,2
QUEUE LINE2
SEIZE CLERK
DEPART LINE2
ADVANCE 100,30
RELEASE CLERK
TERMINATE
GENERATE 28800
TERMINATE 1
import <h4>
module tool_crib_h4
{
facility Clerk;
queue Line1, Line2;
rn_stream Arrive1 seed=100000;
rn_stream Arrive2 seed=200000;
rn_stream Serve1 seed=300000;
rn_stream Serve2 seed=400000;
float shift = 28800;
boolean poisson = FALSE;
int arrived1, arrived2;
int departed1, departed2;
float waited1, waited2;
float busy;
object mechanic1
{
float arrived, service;
actions
{
arrived = time;
arrived1++;
enqueue Line1;
seize Clerk;
depart Line1;
waited1 += time - arrived;
departed1++;
service = rv_uniform(Serve1, 210.0, 390.0);
advance service;
busy += service;
release Clerk;
terminate;
}
}
// mechanic2 is the same with Line2, Serve2 and 70 to 130 seconds
procedure main
{
if (poisson)
{
arrivals: mechanic1 iat = rv_expo(Arrive1, 600.0) priority = 1;
arrivals: mechanic2 iat = rv_expo(Arrive2, 400.0) priority = 2;
}
else
{
arrivals: mechanic1 iat = rv_uniform(Arrive1, 60.0, 780.0) priority = 1;
arrivals: mechanic2 iat = rv_uniform(Arrive2, 120.0, 600.0) priority = 2;
}
advance shift;
report(system);
}
}
deck/tool-crib, with the second mechanic class shortened to a comment here. The poisson switch swaps in exponential arrivals.Class 2 hardly notices the crowd. Class 1 absorbs all of it, and its wait swings by a factor of ten from one shift to the next.
| Measure | Mean of 20 runs | Lowest to highest run |
|---|---|---|
| Class 1 mechanics served | 66.1 ± 1.1 | 61 to 70 |
| Class 2 mechanics served | 80.0 ± 1.7 | 74 to 88 |
| Class 1 mean wait | 954.0 s ± 306.0 | 209.2 s to 2,523.1 s |
| Class 2 mean wait | 140.6 s ± 6.2 | 109.0 s to 170.2 s |
| Clerk utilization | 95.30% ± 1.20 | 90.84% to 99.17% |
± is the 95% confidence interval of the mean over 20 runs. There is no long-run row for the deck as written: with the clerk this close to full, class 1’s line never settles, and a longer run only widens the spread.
Turn on poisson = TRUE and arrivals become exponential, every 600 and 400 seconds on average. The clerk drops to 75% busy and the waits follow Cobham’s formulas for a non-preemptive priority queue. That version, run for two million seconds, is the fourth case on the verification page, and the simulated waits for both classes sit inside their intervals.
GPSS/H is a trademark of its owner. ChiAha is not affiliated with or endorsed by it.