# 4. Adding statistics collection

PREV: 3. Turning it into a real network UP: Contents

## Step 11: Displaying the number of packets sent/received

To get an overview at runtime how many messages each node sent or received, we've added two counters to the module class: numSent and numReceived.

    class Txc11 : public cSimpleModule
    {
      private:
        long numSent;
        long numReceived;

      protected:

They are set to zero and WATCH'ed in the initialize() method. Now we can use the Find/inspect objects dialog (Inspect menu; it is also on the toolbar) to learn how many packets were sent or received by the various nodes.

It's true that in this concrete simulation model the numbers will be roughly the same, so you can only learn from them that intuniform() works properly. But in real-life simulations it can be very useful that you can quickly get an overview about the state of various nodes in the model.

It can be also arranged that this info appears above the module icons. The `t=` display string tag specifies the text; we only need to modify the displays string during runtime. The following code does the job:

            if (ev.isGUI())
                updateDisplay();

    void Txc11::updateDisplay()
    {
        char buf[40];
        sprintf(buf, "rcvd: %ld sent: %ld", numReceived, numSent);
        displayString().setTagArg("t",0,buf);
    }

And the result looks like this:

Sources: tictoc11.ned, tictoc11.msg, txc11.cc, omnetpp.ini

## Step 12: Adding statistics collection

The previous simulation model does something interesting enough so that we can collect some statistics. For example, you may be interested in the average hop count a message has to travel before reaching its destination.

We'll record in the hop count of every message upon arrival into an output vector (a sequence of (time,value) pairs, sort of a time series). We also calculate mean, standard deviation, minimum, maximum values per node, and write them into a file at the end of the simulation. Then we'll use off-line tools to analyse the output files.

For that, we add an output vector object (which will record the data into omnetpp.vec) and a histogram object (which also calculates mean, etc) to the class.

    class Txc12 : public cSimpleModule
    {
      private:
        long numSent;
        long numReceived;
        cLongHistogram hopCountStats;
        cOutVector hopCountVector;

      protected:

When a message arrives at the destination node, we update the statistics. The following code has been added to handleMessage():

            hopCountVector.record(hopcount);
            hopCountStats.collect(hopcount);

hopCountVector.record() call writes the data into omnetpp.vec. With a large simulation model or long execution time, the omnetpp.vec file may grow very large. To handle this situation, you can specifically disable/enable vector in omnetpp.ini, and you can also specify a simulation time interval in which you're interested (data recorded outside this interval will be discarded.)

When you begin a new simulation, the existing omnetpp.vec file gets deleted.

Scalar data (collected by the histogram object in this simulation) have to be recorded manually, in the finish() function. finish() gets invoked on successful completion of the simulation, i.e. not when it's stopped with an error. The recordScalar() calls in the code below write into the omnetpp.sca file.

    void Txc12::finish()
    {
        // This function is called by OMNeT++ at the end of the simulation.
        ev << "Sent:     " << numSent << endl;
        ev << "Received: " << numReceived << endl;
        ev << "Hop count, min:    " << hopCountStats.min() << endl;
        ev << "Hop count, max:    " << hopCountStats.max() << endl;
        ev << "Hop count, mean:   " << hopCountStats.mean() << endl;
        ev << "Hop count, stddev: " << hopCountStats.stddev() << endl;

        recordScalar("#sent", numSent);
        recordScalar("#received", numReceived);
        hopCountStats.recordScalar("hop count");
    }

Unlike omnetpp.vec, omnetpp.sca is not deleted between simulation runs. Instead, new data are just appended to it. The idea is that you can collect output from several simulation runs (i.e. with different input parameters), and analyse them together.

It is possible to use different file names (omnetpp.ini option) so that e.g. multiple runs write to different files.

You can also view the data during simulation. In the module inspector's Contents page you'll find the hopCountStats and hopCountVector objects, and you can open their inspectors (double-click). They will be initially empty -- run the simulation in Fast (or even Express) mode to get enough data to be displayed. After a while you'll get something like this:

When you think enough data has been collected, you can stop the simulation and then we'll analyse the result files (omnetpp.vec and omnetpp.sca) off-line. You'll need to choose Simulate|Call finish() from the menu (or click the corresponding toolbar button) before exiting -- this will cause the finish() functions to run and data to be written into omnetpp.sca.

Sources: tictoc12.ned, tictoc12.msg, txc12.cc, omnetpp.ini

NEXT: 5. Visualizing the results with Plove and Scalars