Once you have defined the driver and the annotations, it is
time to
move to implementing all the details needed for your driver. To start,
we will discuss some of the important characteristics of the driver
object and dice into more detail on the constructor and methods. In
following pages, you will also learn about the timing characteristics
of the driver.
A driver runs in a container which provides services and
invokes the
driver according to the model in the annotations which define the benchmark and the driver.
A driver
class defines one or more operations for
the driver. It may also contain any number of methods which are not
benchmark operations. A driver object is instantiated for each
simulated client thread and remains attached to the client thread until
the end of the benchmark run where the threads, and therefore the
driver objects get terminated. This also means all instance variables
are only used by one thread and therefore access to all instance
variables need not be synchronized. Sharing of information between
operations in the same driver object and thread are done using such
instance variables. Behavior of information sharing between driver
instances and between threads is not defined.
The driver implementor may define as many instance variables as needed. These driver object is not shared between simulated users and threads so access to these instance variables only happen from a single thread. Access to these instance variables need not be synchronized. Following are the common instance variables a driver object will want to keep:
The driver framework demands the driver's constructor to be a public and no-argument constructor. The constructor may throw exceptions. An exception thrown from a constructor is always considered fatal. The benchmark will terminate immediately after a fatal exception.
The driver constructor commonly does the followings:
An
operation is a method annotated with the @BenchmarkOperation
annotation. The
method implementing an operation must be public. The method return type
must be void and the method must not take any arguments. It can throw
any number of exceptions,
both declared and run-time exceptions. Please see Error Handling, for more
information how
the driver is expected to handle the errors
and what the framework will do with the errors.
An operation's logic is typically divided into 3 typical sections:
The Faban Driver Framework measures the response times around the critical section. If manual timing is specified for the operation, the DriverContext.recordTime() method must be called at the beginning and at the end of the critical section. If automatic timing is specified, all timings will be handled by the underlying protocol. Only the critical section will be timed, automatically.
During the critical section, most benchmarks will want to communicate
with the server or the system under test. Please see "Communicating with the SUT"
for more
detail.
The Faban driver framework automatically collects vital statistics such as throughput, response times, cycle times, and generates a standard xml report with all the measurements. Many benchmarks will however wish to collect certain statistics beyond that. We will call them custom statistics or miscellaneous statistics. In order to collect miscellaneous statistics, the driver implementor will need to implement a CustomMetrics class and ensure that all stats are collected and reported there. Please see "Metrics, Data Collection, and Reporting" for more detail.