In this section we will reveal as much details about message generators as possible. First we describe the architecture and then we discuss an approach to develop a new generator.
Generator is the most sensitive and fragile component in the whole PerfCake architecture.
It has the reponsibility of generating all the messages and load. It is recommended to study
as its basic implementation and then the default implementation called
DefaultMessageGenerator before developing your own generator.
The main responsibility of the generator is creation of
whil controlling the number of threads used and the speed of creation of these tasks. A
generator also keeps a thread pool that executes the tasks. The tasks are then processed as
fast as possible. There is nothing a generator could or should do about the speed of the
A message generator is the most crucial and complicated component of PerfCake and it is highly recommended to reuse one of existing implementations as they already offer mostly wanted features.
The message generator needs to take care of the sending threads, create
SenderTasks as needed and monitor the test progress. It is important to
properly shutdown the message generation for both time and iteration based test length
control. In the case of an iteration based control, a generator must wait for all the tasks to
be processed (in case of a normal/unexceptional termination). In the case of a time based
control, the test stops immediately after the time has elapsed.
SenderTask takes a reference to its parent generator to notify this
generator of any errors that might have occurred.
A message generator carries links to all other system components and thus has an ultimate
control over the running performance test. It is the only class that indirectly manipulates
RunInfo through starting and stopping the
A message generator usually maintains a queue of prepared
schedules their execution. It also controls the number of parallel threads running.
The best way to implement a new generator is by modifying
DefaultMessageGenerator. The main method is
generate() that creates a new thread pool and generates
SenderTasks until the test is finished.
SenderTasks are submitted as tasks to the newly created thread
pool. In the end the thread pool is shut down according to
configuration as described in the previous section.
It is worth noticing the custom thread factory
DefaultMessageGenerator.DaemonThreadFactory. This makes sure we
can quit the process even if some threads got stuck. It also sets higher priority to
DefaultMessageGenerator keeps an eye on the number of prepared
SenderTasks by using a BlockingQueue that is passed to the
underlying thread pool executor. This limits the size of memory used at once.
Now investigate the
to see how
SenderTasks are created. You can notice that SenderTasks
constructors takes the generator to be able to report failures back. Other test
execution related classes are set on the
SenderTask as well for it to be
able to complete its goal. A
SenderTask instance implements
Runnable and except for default Java API, there is no notification of
In the end just have a look to the
SenderTask class. This class
Runnable and does the following steps. First, it acquires
MessageSender from the senders pool, uses this
MessageSender to send one or more messages while measuring the
time it took. When a
Receiver is used, it awaits for a message response on
a separate message channel. Upon the response's arrival, the total time is measured. In
the end, the
MessageSender is released. When a
is in place, the
MessageSender is not returned to the pool until we get a
response corresponding to the original request. This prevents another thread from using
MessageSender and thus increasing the number of concurrent