Concepts

The following sections will describe the concepts and components used within Basher in more detail.

Overview

Tasks

At a high level, the typical Basher setup contains of any number of small task instances, configured by a task configuration. The combination of a task and a task configuration is called a task contribution. The task contribution is provided to the task manager, which manages task contributions at runtime.

Task - TaskContribution TaskManager - TaskConfiguration

Runs and Contexts

A Run a set of threads executing available tasks according the configuration in a context. The context defines how long the different phases of a run should be (phases are explained below), how many threads should be used to execute the tasks, when statistics collection should be done and so forth. Take a look at the contest Javadoc for more information.

Contexts are managed by the context mananger, which handles the adding, removing and marking contexts as active.

BasheContext - ContextManager

Life-cycle States & Phases

These components together form the parts required to perform a Basher 'run', which in Basher consists of 7 different life-cycle states & phases:

  • Start: Initial state when system is started
  • Setup: Phase in which setup of required data, configuration, etc can be done.
  • Warm-up: Initial phase before a run is started. This phase can be used to 'warm-up' the JVM & HotSpot.
  • Run: The main phase where 'work' actually happens. This phase is also the phase in which statistics is captured
  • Cool-down: Phase allows tasks to complete their work, but statistics is not captured for these tasks.
  • Tear-down: Phase used to close any open resources
  • End: End state of when all work has been completed.

Tasks can be configured to run in different life-cycles, to allow one task to, for example, create pre-requisite data, while another task uses thi data in the Run

Phase

Infrastructure

Internally, Basher uses Gaderian, which allows easy configuration and bootstrapping functionality. It also allows a very complete system to be built up around the running tasks without Basher having necessarily to know about it.

Below follows a summary of the main components within Basher and how to use and interact with them.

Task

A task is the key component to the Basher. It is defined as an interface to be implemented by the application developer and is the link between Basher and the application being tested and provides Basher with the work it is intended to measure. For convenience, Basher has a default implementation of the Task interface available called AbstractTask that provides some helper methods for managing errors and the like during a run.

The only thing a task is required to expose is a method to be executed as part of a run. The default name of this method is executeTask.

Task

Timed Task

A timed task is the 'special' form of task within the Basher system. It is still an instance of the Task interface, but (as the name may indicate) it is executed in a timed (interval) fashion. It allows certain operations to happen at certain points in the performance test run.

The timed task has the same properties as any other task.

Followers

In many usage scenarios, tasks usually consists of a set of consecutive steps (or smaller tasks). Basher provides a way for defining a set of tasks that logically follow their "parent" task. For example, a "create account" task is usually followed by a "login task". Note that the use of 'usually' is important in this context since the task may *not* always run.

The concepts of 'followers' allows for complex usage scenarios to be easily modelled by combining a set of smaller tasks.

Task Configuration

A task configuration specifies the behaviour of the task, the way it will be executed by Basher.

The following key properties (defined as simple java bean properties) are captured by the task configuration:

Task Configuration Properties
PropertyDescriptionDefault
nameThe name of the task. This name can be used to retrieve the task from the task manager by it's nameFully qualified class name
weightThe chance for the task to be invoked100 (always)
inertiaThe amount the weight should be multiplied by for every successful invocation (a float between 0 and 2)1.0 (no intertia)
runFromSpecified the time (in seconds) before which the task should not execute0 (run from start)
stopAfterSpecifies the time (in seconds) from which point the task should not execute furtherLong.MAXVALUE (run till end)
maxInvocationsSpecifies maximum number of times Basher is allowed to invoke the task0 (no maximum)
phasesSpecifies the phases in which the task should be executedRUN

TaskConfiguration

Basher Context

The context controls all aspects of a run. It defines the number of threads, the length of the various phases, when collection is done, etc.

The following properties are configurable through the BasherContext:

BasherContext Properties
PropertyDescriptionUsageDefault
nameName of the context. Used for look-ups of the contextsRequiredNo default
runIdentifierIdentifier to used for the runOptionalno default
manuallyControlledFlag indicating that phase transitions are controlled by Basher (default behaviour) or by the user, using for example BeanShellOptionalfalse (phase transitions handled by Basher)
setupDurationDefines the length of the setup phase (defined in seconds)Optional10 seconds
warmupDurationDefines the length of the warmup phase (defined in seconds)Optional0 seconds
runDurationDefines the length of the run phase (defined in seconds)Optional10 seconds
cooldownDurationDefines the length of the cooldown phase (defined in seconds)Optional10 seconds
teardownDurationDefines the length of the teardown phase (defined in seconds)Optional0 seconds
startCollectionFromDefines delay before statistics collection should begin (in the run phase)OptionalNo default (start collection immediately)
stopCollectionAfterDefines delay before statistics collection should stop (in the run phase)OptionalNo default (stop collection at the end of run phase)
initialNumberThreadsNumber of threads which are created at the start of a runOptional10
maxNumberThreadsMaximum number of threads that may exist in the system (used normally in combination with thread incrementors)Optional0 (no maximum)
threadIncrementIntervalInterval between adding more threads to the runtimeOptional0 (no incrementing of threads)
threadIncrementCountNumber of threads to be added for each interval. Only used if threadIncrementInterval is definedOptional0
taskMinDelayMinimum delay between tasks. Mainly used to stagger execution of tasksOptional0 (no delay)
taskMaxDelayMaximum delay between tasks. Mainly used to stagger execution of tasksOptional0 (no delay)
markAverageIntervalInterval at which execution averages are calculated. Defined in secondsOptional10 seconds
beanShellScriptDirectoryName of directory containing BeanShell scripts to use during initializationOptionalsrc/main/beanshell
reportDirectoryName of the directory of where reports should be capturedOptionaltarget/basher-reports/
includesComma separated string containing include patterns (net.sourceforge.basher.example.tasks.*,com.acme.tasks.*)Optional* (all tasks)
includesComma separated string containing exclude patterns (net.sourceforge.basher.example.tasks.*,com.acme.tasks.*)Optional* (all tasks)

BasherContext

TaskManager

The task manager is responsible for managing tasks within the Basher. All tasks must be registered with the task manager in order to be executed within a given testing scenario. It will, upon request, select a task randomly from the pool of available tasks and return it to the caller.

The selection algorithm is currently entirely random and is simply a random index, based on the size of the pool.

TaskManager

Scheduler

The scheduler is the default (and currently the only) service responsible for managing life-cycles within the system. It creates and starts an initial number of threads that in turn are responsible for executing the tasks registered within the system. It will also maintain state transitions between phases.

By default, the scheduler will start up 10 threads, but this can be overridden by specifying your own value for the 'initialNumberThreads' property in the BasherContext.

If not using the Maven plugin, the scheduler can be started by obtaining a reference to it through the Gaderian registry and execute the start() method.

...
Registry registry = ...
Scheduler scheduler = (Scheduler)registry.getService(Scheduler.class);

scheduler.start();

... do some waiting while the tasks run

scheduler.stop(); // Shuts the scheduler down again
...

Thread Incrementors

In some cases, it may desirable to increment (ramp up) the number of threads that are used during the run. This can either be done using BeanShell (by interacting with the Scheduler) or by using the thread incrementor functionality built into Basher.

By default, this functionality is not active, but can be set to increment the number of threads by X at an interval of N by defining the properties 'threadIncrementCount' and 'threadIncrementInterval' respectively in the BasherContext.

Scheduler - BasherContext

Event Manager

Internally, Basher uses an event driven approach to inform interested parties about life-cycle transitions, task management and various other information.

The event manager API is the main entry point into the events sub-system.

The current set of events available:

  • CollectionStartedEvent: Raised when collection is about to be started
  • CollectionStoppedEvent: Raised when collection is about to be stopped
  • NoTasksAvailableEvent: Raised when the task manager has run out of tasks to select from during a phase
  • TasksAvailableEvent: Raised when the task manager again has tasks available to select from during a phase
  • ThreadAddedEvent: Raised when a thread has been added
  • ThreadRemovedEvent: Raised when a thread has been removed
  • TickEvent: Raised when a 'tick' occurs in the system. A tick is the interval between capturing averages
  • PhaseTransitionEvent: Raised when a phase transition (setup->run for phase transition for example)

Custom events may be published through the EventManager by extending the BasherEvent class and publishing them using the publish() method of the EventManager.

Note: The event management system if currently single-threaded but this may move to being multi-threaded going forward.

EventManager - BasherEvent

Context Manager

The context manager is responsible for managing (mainly storing) registered Basher contexts at runtime. The contexts can be provided to the context manager by contributing to the net.sourceforge.basher.BasherContexts configuration point & and at runtime, using the add method.

The following is an example of contributing a Basher context using Gaderian:

...
  <contribution configuration-id="BasherContexts">
    <basher-context name="default" setup-duration="10" run-duration="20" cooldown-duration="10"
                    start-collection-from="0"
                    stop-collection-after="0" initial-number-threads="5"
                    max-number-threads="5" thread-increment-count="0"
                    thread-increment-interval="0" mark-average-interval="10"
                    task-min-delay="0" task-max-delay="1"
                    report-directory="target/basher-reports"
            />
  </contribution>
...

Using the getActiveBasherContext method, it is possible to retrieve the currently active BasherContext.

ContextManager - BasherContext

Miscellaneous

Bean Shell

Basher also offers the facility of configuring a set of task (based on the registered tasks) using BeanShell. This allows for an quick and easy way of building up fairly complex scenarios using Basher.

When a phase transition occurs, the BeanShell initializer will invoke all Beanshell scripts found in the directory defined by the 'beanShellScriptDirectory' property in the BasherContext. By default, it will try to match the files in the directory matching the regular expression 'S[0-9][0-9]{0,1}-.*\.bsh' and execute the in the order defined by the numbers by the filename.

The Beanshell interpreter is initialized with the following services:

  • scheduler
  • taskManager
  • eventManager
  • currentPhase
  • currentBasherContext

The below script is an example of a script that removes all registered tasks and then adds one single task that will be run by the Basher.

tasks = taskManager.getTasks();

tasks = new java.util.ArrayList(tasks);

for (java.util.Iterator itr = tasks.iterator(); itr.hasNext();)
{
  task = itr.next();
  taskManager.removeTask(task);
}


task = taskManager.getTaskByName("HelloWorldTask");
task.setMaxInvocations(0);
task.setWeight(100);
taskManager.addTask(task);