Resource Pool

A limited number of units that entities take, hold and return. No connections.

How it works#

The Resource Pool is a limited number of identical units that entities take, hold across several steps and return. It stands for anything a request has to keep hold of while the work is done somewhere else: a database connection, a thread, a licence, a bed.

Unlike every other component, it has no input and no output, and nothing is connected to it. It sits beside the flow. An Acquire placed in the flow names the pool and takes a unit from it for each entity that passes, and a Release further on gives it back. A unit takes no time of its own: the time it is held is the time the entity spends in whatever lies between the two.

When every unit is held, an entity that asks for one waits. A pool keeps one waiting line, in arrival order, across every Acquire that names it, and a returned unit goes to the entity that has waited longest, whichever Acquire it stands at. There is no priority among waiting entities and no limit on how many can wait. What bounds the line is time: an entity that has waited for the Acquire Timeout is dropped.

A unit can never leak. Every unit an entity still holds returns to the pool when the entity leaves the model, whether it completed or was dropped anywhere along the way.

Settings#

Capacityunits, 1 to 1000 — default 10
How many units entities can hold at once. When all of them are held, the next entity to ask for one waits.
Acquire Timeoutseconds, 0 to 3600 — default 30
How long an entity waits for a unit before it is dropped. With 0, an entity that finds no free unit is dropped at once.

Both can be changed while the simulation runs. Raised capacity is handed at once to the entities that have waited longest. Lowered capacity never takes a unit from an entity holding one: the units already out stay out, and no returned unit is handed on until fewer are in use than the new capacity. A new Acquire Timeout applies to the entities already waiting as well, counted from the moment each one arrived, so shortening it can drop some of them straight away.

Acquire and Release#

A pool does nothing until an Acquire names it. Acquire and Release each have a single setting, Pool, which chooses one of the resource pools on the canvas. The chosen pool's name is shown under the node, and it cannot be changed during a run. A run will not start while an Acquire or a Release has no pool.

  • An Acquire gives each entity one unit. An entity that finds a free unit takes it and passes on at once. Otherwise it waits at the Acquire, up to the pool's Acquire Timeout, and is then dropped and counted against that Acquire.
  • A Release returns one unit of its pool as the entity passes through, and the entity carries on at once. It is optional: without one, the unit returns when the entity leaves the model.

Several Acquires and Releases can name the same pool, which is how separate paths through a model compete for one resource. An entity can also hold units of several pools at once — a thread and a connection, say — by passing through an Acquire for each.

Statistics#

  • Units in use — how many units are held, over time. A line that sits at the capacity means entities are waiting for the pool.
  • Requests waiting — how many entities are waiting for a unit, over time, in total across every Acquire that names the pool.
  • Time a unit is held — the mean time, in seconds, over the chart window. It runs from the moment a unit is taken to the moment it is returned; a unit still held when the run ends is not counted.
  • After a batch run, the mean units in use, the mean requests waiting and the time a unit is held, each as a mean per run with a confidence interval. Time a unit is held is the mean in Basic mode and the mean, median, 95th and 99th percentile in Advanced mode; a hold that began during the warm-up is left out.

How long entities waited, and how many were served and dropped, is reported by each Acquire.

Example: a connection pool#

The Connection pool model in the library is ready to run. Two paths share one pool of 5 connections with an Acquire Timeout of 5 seconds. Orders arrive at 8 a second, take a connection, run a query of 0.2 seconds on average, return the connection, and then spend 0.2 seconds confirming the order. Reports arrive at 1 a second, take a connection, run a query of 3 seconds on average, return it, and then spend 1 second building the report.

Over a simulated hour about 4.5 of the 5 connections are in use, and about 14 entities are waiting for one. An order waits about 1.5 seconds for a connection it then holds for 0.2, and between 2 and 3 in every 100 entities are dropped on the timeout. The reports are one arrival in nine but hold about three of the five connections, so the slow reports starve the fast orders.

Raise Capacity to 8 while it runs. The line in front of the pool drains, the wait falls to about a twentieth of a second and the drops stop, although the pool is no busier than before: on average fewer than 5 connections are in use.

Both paths return the connection with a Release straight after the query. Without it each entity would keep its connection through the last step as well, until it left the model.