[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
As mentioned in the Using the Tracing System section, the whole point of running
an ns-3
simulation is to generate output for study. You have two basic
strategies to work with in ns-3
: using generic pre-defined bulk output
mechanisms and parsing their content to extract interesting information; or
somehow developing an output mechanism that conveys exactly (and perhaps only)
the information wanted.
Using pre-defined bulk output mechanisms has the advantage of not requiring any
changes to ns-3
, but it does require programming. Often, pcap or NS_LOG
output messages are gathered during simulation runs and separately run through
scripts that use grep, sed or awk to parse the messages and reduce and transform
the data to a manageable form. Programs must be written to do the
transformation, so this does not come for free. Of course, if the information
of interest in does not exist in any of the pre-defined output mechanisms,
this approach fails.
If you need to add some tidbit of information to the pre-defined bulk mechanisms,
this can certainly be done; and if you use one of the ns-3
mechanisms,
you may get your code added as a contribution.
ns-3
provides another mechanism, called Tracing, that avoids some of the
problems inherent in the bulk output mechanisms. It has several important
advantages. First, you can reduce the amount of data you have to manage by only
tracing the events of interest to you (for large simulations, dumping everything
to disk for post-processing can create I/O bottlenecks). Second, if you use this
method, you can control the format of the output directly so you avoid the
postprocessing step with sed or awk script. If you desire, your output can be
formatted directly into a form acceptable by gnuplot, for example. You can add
hooks in the core which can then be accessed by other users, but which will
produce no information unless explicitly asked to do so. For these reasons, we
believe that the ns-3
tracing system is the best way to get information
out of a simulation and is also therefore one of the most important mechanisms
to understand in ns-3
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There are many ways to get information out of a program. The most straightforward way is to just directly print the information to the standard output, as in,
#include <iostream> ... void SomeFunction (void) { uint32_t x = SOME_INTERESTING_VALUE; ... std::cout << "The value of x is " << x << std::endl; ... }
Nobody is going to prevent you from going deep into the core of ns-3
and
adding print statements. This is insanely easy to do and, after all, you have
complete control of your own ns-3
branch. This will probably not turn
out to be very satisfactory in the long term, though.
As the number of print statements increases in your programs, the task of
dealing with the large number of outputs will become more and more complicated.
Eventually, you may feel the need to control what information is being printed
in some way; perhaps by turning on and off certain categories of prints, or
increasing or decreasing the amount of information you want. If you continue
down this path you may discover that you have re-implemented the NS_LOG
mechanism. In order to avoid that, one of the first things you might consider
is using NS_LOG
itself.
We mentioned above that one way to get information out of ns-3
is to
parse existing NS_LOG output for interesting information. If you discover that
some tidbit of information you need is not present in existing log output, you
could edit the core of ns-3
and simply add your interesting information
to the output stream. Now, this is certainly better than adding your own
print statements since it follows ns-3
coding conventions and could
potentially be useful to other people as a patch to the existing core.
Let’s pick a random example. If you wanted to add more logging to the
ns-3
TCP socket (tcp-socket-impl.cc
) you could just add a new
message down in the implementation. Notice that in TcpSocketImpl::ProcessAction()
there is no log message for the ACK_TX
case. You could simply add one,
changing the code from:
bool TcpSocketImpl::ProcessAction (Actions_t a) { // These actions do not require a packet or any TCP Headers NS_LOG_FUNCTION (this << a); switch (a) { case NO_ACT: NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action: NO_ACT"); break; case ACK_TX: SendEmptyPacket (TcpHeader::ACK); break; ...
to add a new NS_LOG_LOGIC
in the appropriate case
statement:
bool TcpSocketImpl::ProcessAction (Actions_t a) { // These actions do not require a packet or any TCP Headers NS_LOG_FUNCTION (this << a); switch (a) { case NO_ACT: NS_LOG_LOGIC ("TcpSocketImpl " << this << " Action: NO_ACT"); break; case ACK_TX: NS_LOG_LOGIC ("TcpSocketImpl " << this << " Action: ACK_TX"); SendEmptyPacket (TcpHeader::ACK); break; ...
This may seem fairly simple and satisfying at first glance, but something to
consider is that you will be writing code to add the NS_LOG
statement
and you will also have to write code (as in grep, sed or awk scripts) to parse
the log output in order to isolate your information. This is because even
though you have some control over what is output by the logging system, you
only have control down to the log component level.
If you are adding code to an existing module, you will also have to live with the output that every other developer has found interesting. You may find that in order to get the small amount of information you need, you may have to wade through huge amounts of extraneous messages that are of no interest to you. You may be forced to save huge log files to disk and process them down to a few lines whenever you want to do anything.
Since there are no guarantees in ns-3
about the stability of NS_LOG
output, you may also discover that pieces of log output on which you depend
disappear or change between releases. If you depend on the structure of the
output, you may find other messages being added or deleted which may affect your
parsing code.
For these reasons, we consider prints to std::cout
and NS_LOG messages
to be quick and dirty ways to get more information out of ns-3
.
It is desirable to have a stable facility using stable APIs that allow one to reach into the core system and only get the information required. It is desirable to be able to do this without having to change and recompile the core system. Even better would be a system that notified the user when an item of interest changed or an interesting event happened so the user doesn’t have to actively poke around in the system looking for things.
The ns-3
tracing system is designed to work along those lines and is
well-integrated with the Attribute and Config subsystems allowing for relatively
simple use scenarios.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated by root on May 3, 2010 using texi2html 1.82.