2009年2月4日星期三

The Importance of not Using "bind()" in NS2

As described in my last post, I used valgrind to find out the memory usage of my simulator. Finally, I found that a invocation of "bind()" in UdpAgent::UdpAgent()" consumes most memory. That reminds me that the ns2 manual recommends to use dynamic binding instead of "bind" when the object of a class is frequently created. In my case, the P2P application requires two UdpAgents for a connection. Since the connections are created and removed constantly, the memory consumed by bind() keeps increasing. To solve this problem, I modified class UdpAgent as follows:

apps/udp.h
add two declarations:
virtual void delay_bind_init_all();
virtual int delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer);
apps/udp.cc
delete "bind("packetSize_", &size_);" in UdpAgent::UdpAgent() and UdpAgent::UdpAgent(packet_t type)
add two definition:
void UdpAgent::delay_bind_init_all()
{
delay_bind_init_one("packetSize_");
Agent::delay_bind_init_all();
}

int UdpAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
{
if (delay_bind(varName, localName, "packetSize_", &size_, tracer))
return TCL_OK;
return Agent::delay_bind_dispatch(varName, localName, tracer);
}

Then type "make clean; make" to rebuild ns2. Now the memory usage and simulation time is reduced significantly.

I'm not very clear about what does it do when "bind()" is invoked and why the memory is not released even when the UdpAgent object is deleted. Anyone who knows the answer please post me a message.

Profiling Memory Usage for NS2 Simulation

I am using ns2 to simulate peer-to-peer networking. However, it turns out that the simulator consumes much more memory than I expected. I am sure that my algorithm could not use so much memory. What's happening during the simulation.

I tried dmalloc, but it seems that the dmalloc supporting in ns2 is out-of-data and causes some error. Finally I gave up dmalloc and turned to valgrind.

I used valgrind to detect memory leaks and errors. Today I learned that it can also do memory usage profiling.

First, you have to pass '-g' option to compiler and re-make ns2. It is recommended to remove any optimization flags when debugging.

Then run your program by typing "valgrind --tool=massif ns test_script.tcl". BTW, I recommend u to specify a threshold for massif by using "valgrind --tool=massif --threshold=0.01 ns test_script.tcl" to get more detailed information.

massif will generate a report in current directory. The default name is massif.out.pid, where pid is the process number.

massif.out is a plain text file. Though u can read it directly, there is another helpful tool, ms_print to gather information in the report and print it more readable. Use ms_print --threshold=0.01 massif.out to format the report.

The output of ms_print is very easy to understand and the online document of valgrind has a detailed description about that. Please refer to http://valgrind.org/docs/manual/ms-manual.html

2009年2月3日星期二

Enable DMalloc support for NS2

Since my NS2 eats too much memory, which makes the simulation not scalable, I was trying to profile the memory usage by enable dmalloc support for NS2.

Originally I download ns-2.33-all-in-one and install it on my Ubuntu 8.04 Linux.

The NS2 manual seems to show that it very easy to enable dmalloc for NS2, but it's kinda out of date.

First, ns2 needs an old version of dmalloc, for example, I use dmalloc-4.8.2. If u use dmalloc-5.5.1, compiler will complain "_malloc_leap was not declared in this scope"

Extract and drop dmalloc-4.8.2 in the parallel directory of ns-2.33, build it using "./configure" and "make". "make install" is unneccessary. If you use "make install" to install dmalloc in your system, the configure script of ns-2.33 will complain "checking for return.h... no".

Change working directory to ns-2.33, type " ./configure --with-otcl=../otcl-1.13 --with-tclcl=../tclcl-1.19 --with-dmalloc=../dmalloc-4.8.2", it will generate Makefile for you.

Try "make" in ns-2.33, a link error occur: multiple definition of TclpAlloc. This is because libtcl8.4.a already defines TclpAlloc and ns-2.33/lib/dmalloc_support.cc tries to redefine it. I actually have no idea of how to solve this problem. A temporary solution is, if u do not care about the memory TclpAlloc and Tcl_Alloc, just comments out the definition of these two funtions in dmalloc_support.cc and then compilation will success.

After building ns2 with dmalloc, then u can follow the steps in ns2 manual except for the one adding alias for bash. It seems to be a typing error in my ns2 manual. The correct alias should be: function dmalloc { eval `command dmalloc -b $*`; }

That's all.