Measurement Sources

Introduction

openWNS decouples the generation and evaluation of measurements. The evaluation, may that be logging, filtering, sorting or simply storing them is described in detail in Evaluation Framework. In the following, the focus is solely on the generation of measurements and adding context information to them, which than may be processed by the evaluation framework.

Concept

In the following we will be making use of some fundamental conecepts regarding the implementation of measurement sources, which will be defined now.

Measurement Source
A measurement source is a logical concept that describes a location within the simulator where a measurement value is measured and is made available to the evaluation framework. A measurement value has a timestamp, which holds the time when the measurement value was generated. A measurement value may have context information.
Measurement Value
A double value representing a measurement of some phenomenon in your simulator
Context
A dictionary mapping an arbitrary but unique name to an int value. The context captures the state (within a certain scope) of your simulator when a measurement value is measured.

Realization

Measurement sources, values and their context information is realized by wns::probe::bus::ProbeBus. The ProbeBus realizes the connection of measurement sources to the evaluation framework. wns::probe::bus::Context realizes the context information.

Commonly, the entries in the context information of each measurement source do not change during the whole simulation (of course the value of each entry changes over time, but not the name). In such cases the wns::probe::bus::ContextCollector should be used to automatically generate the context information and the timestamp when a measurement souce generates a measurement value and passes it on to the evaluation framework. The wns::probe::bus::ContextProviderCollection and wns::probe::bus::ContextProvider are used to define which context information is to be gathered by the wns::probe::bus::ContextCollector.

Implementing a Measurement Source

To add a measurement source to some class of your simulator you need to add

#include <WNS/probe/bus/ProbeBus.hpp>
#include <WNS/probe/bus/ProbeBusRegistry.hpp>

to the header file of that class. Suppose you have implemented a simple queueing model with a Job class that has some priority and that records the time when processing started. It may look like this:

class Job
{
public:
    enum Priority
    {
        control = 0,
        realtime,
        multimedia,
        bestEffort
    } priority;

    Job();

    Job(const Job&);

    Priority priority_;

    wns::simulator::Time startedAt_;

};

Furthermore, let us say that you have a class Processor that will process a Job and then generate a measurement of the processing time. The context of this measurement will be the Job‘s priority class. The Processor class may look like this:

class Processor
{
public:

    Processor();

    void
    startJob(Job job);

    void
    onJobEnded(Job job);

private:
    boost::shared_ptr<wns::distribution::Distribution> dis_;

    wns::probe::bus::ProbeBus* probeBus_;
};

The class has two methods startJob() and onJobEnded. It has a distribution member variable to draw randomly distributed processing delays. To generate measurements we need a pointer to a wns::probe::bus::ProbeBus. This is your connection point to the evaluation framework. Let’s have a look at the constructor of Processor.

Processor::Processor():
    dis_(new wns::distribution::Uniform(0.0, 1.0)),
    probeBus_(NULL)
{
    wns::probe::bus::ProbeBusRegistry* reg = wns::simulator::getProbeBusRegistry();
    probeBus_ = reg->getMeasurementSource("processor.processingDelay");

    assure(probeBus_ != NULL, "The probeBus_ is NULL");
}

To initialize our ProbeBus we ask the wns::probe::bus::ProbeBusRegistry to create one for us and register it with a unique name. Since we want to measure processing delay we choose the name processor.processingDelay. You should always prefix your measurement source name with the namespace of your class to make it unique. You will see in Evaluation Framework that this name is used to connect your evaluation to the measurement source.

Let’s see what happens if someone request the processor to start a job. Here is startJob:

void
Processor::startJob(Job job)
{
    wns::events::scheduler::Interface* scheduler = wns::simulator::getEventScheduler();

    job.startedAt_ = scheduler->getTime();

    wns::simulator::Time processingTime = (*dis_)();

    wns::events::scheduler::Callable jobEndsCallable =
        boost::bind(
            &Processor::onJobEnded,
            this,
            job);

    scheduler->scheduleDelay(jobEndsCallable, processingTime);
}

We get the event scheduler and record the current time in the job.startedAt_. Then we draw a random processing time form the distribution and schedule a delayed call to our the onJobEnded method. If you do not understand how the scheduling works please read The Event Scheduler first.

So let’s see how to generate the processing delay measurements. This is done int onJobEnded.

void
Processor::onJobEnded(Job job)
{
    // Create the context and populate it
    wns::probe::bus::Context context;

    context.insertInt("priority", job.priority_);

    // Get the current time
    wns::events::scheduler::Interface* scheduler = wns::simulator::getEventScheduler();

    wns::simulator::Time timestamp = scheduler->getTime();

    // Create the measurementValue
    double measurementValue = timestamp - job.startedAt_;

    assure(probeBus_ != NULL, "The probeBus_ is NULL");

    // Pass it all to the evaluation framework
    probeBus_->forwardMeasurement(timestamp,
                                  measurementValue,
                                  context);
}

Since we want to provide context information for our measurement value we first create an empty wns::probe::bus::Context and populate it with the job’s priority which we read from the Job itself. Then we get the current time from the scheduler and calculate the measurement value, which is simply the current time minus the job’s start time, i.e. the processing delay.

Everything is prepared now. We have the measurement value, the timestamp and the context. To pass it on to the evaluation framework, we first assure that probeBus_ is not NULL and then call forwardMeasurement of our probeBus_.