Simulation control and debugging

We’ve already seen how to control the simulation speed and limit the run time. And of cause you can output debug messages using the print() method. But there are also some other ways to observe and influence the simulation.

Statistics

There are different points to see statistics in the main window. In the upper right area you may see statistics for a single node just as you called a message in a previous chapter. In the tab “Status” you can see the maximum and the average size of the input buffer for the specific node. in the tab “Method statistic” you can see how many times a method is called on this specific node. Try it out: Start your grid message example and send a message from node 1 to node 8. You can see, the method message is called one time on node 1, 6, 7 and 8 but not at all on the other nodes.

Beside that node specific statistics there are global statistics as well. You can find them in the left area directly below the node generation area. This statistics include the total number of nodes and the nodes divided by status. What a status is you may see in the next section. Beside that numbers you can see the maximum and averade buffer size of all nodes. To see the number of method calls per method over all nodes on total and in average, you can click on “show method call statistics”. Click on that button. After our example from above we can see the message method is called four times, which is exactly the number of nodes the message passed.

Sleeping, dead and other nodes

So far, all nodes in the visualization where blue or orange. Orange means the node is selected for the main window independent from the nodes actual status. Blue means the node is running.

Let’s explore other cases. Start NetSimLan again with your grid message program but without a graph file. Create a graph as before but this time, uncheck “Autostart”. You see the nodes are black meaning they aren’t started yet. Also no edges are displayed for they are in the input buffer of the nodes but not established yet. Select one node and press start in the “Status” tab in the node area. Now two things happen. First the outgoing edges for that node are created and painted. Second it’s painted blue after selecting another node. Have a look at the statistics area in the global area of the main window. You can see the number of total nodes 25, one node started and 24 waiting to be started. You can start every node this way separately to simulate a slow start of your network. To be more fast than starting many nodes by hand you may simply press “Start all nodes” in the global statistics area. Now it’s time to start them to get the grid working.

A node can also sleep. Sleeping means it don’t act by itself anymore, especially doesn’t call timeout() anymore. It wakes up as soon as the next message arrives. This can be used for leaving processes. Let’s try it out: select node 6, in the node status area click on “set asleep” and select node 1 again. You see node 6 is yellow now which shows it’s sleeping. Send a message from 1 to 8 again. As you can see node 6 turns blue again. You can also set all nodes asleep using the corresponding button in the global statistics area. Try it out. Set all nodes asleep, send a message through the network and see how the nodes in the route to the destination wake up. When a node should go asleep by itself you may call the build in function sleep(). In context it may looks as follows:

goodby (){
    print("I'm tied");
    sleep();
}

Finally a node can be dead. A dead node doesn’t do anything and can represent an hardware defect or a shutdown without message. Redo the example from above now for dead nodes: select node 7 this time, in the node status area click on “Kill” and select node 1 again. You see node 7 is red now meaning it’s dead. Send a message from 1 to 8 again. You can now follow the marks and see, the message never passes node 7 and never reaches 8. This shows our routing protocol isn’t robust against hardware failures. As setting it asleep you can let a node kill itself by calling kill().

Pause and breakpoints

In cases you’d like to study your simulation in detail, you can pause it. Go to the global statistics area and find the button “Pause simulation”. To try it out, send a message through your grid and press the pause button. Think of the fact you can slow down the simulation if the message deliveres to fast. You now may have a deeper look in the state of your network and nodes and afterwords continue by pressing the same button again.

You can also pause the simulation automatically by adding breakpoints. Breakpoints can be enabled or disabled in the global statistics area right under the pause button. They are disabled by default if the main window is hidden or enabled otherwise. To insert a breakpoint in your program just add the keyword BREAKPOINT. This may looks as follows in our grid example:

message (string text, int to_id){
    int x_n=(to_id-1)/size; int y_n=(to_id-1)%size;
    if (x_n == x_this & y_n == y_this) {
        print("Message " + text + " received.");
    } else if (x_this != x_n) {
       if (x_n < x_this)
            left -> message(text, to_id);
        else
            right -> message(text, to_id);
    } else {
        if (y_n < y_this)
            bottom -> message(text, to_id);
        if (y_n > y_this)
            top -> message(text, to_id);
    }
    mark (true);
    BREAKPOINT
}

Visualization management

You can move the nodes in the visualization using the right mouse key. Typical nodes are positioned automatically. To turn of this behavior have a look at the last section in the global area of the main window labeled “Visualization”. Find the button “Disable auto position of nodes”.

In this area you can also hide the node names and decrease the color of edges. Both is made as a solution for cases with many nodes or edges where the node labels or edges make each other hard to notice.

Whenever a node introduces itself or a third node to another but that message hasn’t reached its destination yet, that’s called an implicit edge. They aren’t important to our grid example but may be very important to other examples like self stabilization. By default this edges aren’t displayed, but you can display them using the button “Show implicit edges”. Be aware that only implicit edges generated after the button click are displayed. Note on graph files: Last chapter you’ve seen how to store a graph in an file and load it. The selections to auto layout nodes and to show implicit edges is also stored there.

Since implicit edges aren’t important to your grid-example you may use the following example to toy around with them. This example will build a list our of any connected graph. Also fell free to generate any kind of random or structured graph to test it.

listNode {
    node left; node right;
    entry(node V){
        if (id(V)<id(this)){
            if (left==null){
                left=V;
            }else{
                if (id(left)<id(V))
                    { V->entry(left); left=V; }
                else left->entry(V);
            }
        }else if(id(V)>id(this)){
            if (right==null){
                right=V;
            }else{
                if (id(right)>id(V))
                    { V->entry(right); right=V; }
                else right->entry(V);
            }
        }
    }
    timeout(){
        left -> entry(this);
        right -> entry(this);
    }
} 


Previous: Automated runs Next: Data types, variables, and operations

The University for the Information Society