debug.tex
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:11k
源码类别:

通讯编程

开发平台:

Visual C++

  1. chapter{Debugging ns}
  2. label{sec:debug}
  3. ns is a simulator engine built in C++ and has an OTcl (Object-oriented
  4. Tcl) interface that is used for configuration and commands. Thus in order
  5. to debug ns we will have to deal with debugging issues involving
  6. both OTcl and C++. This chapter gives debugging tips at Tcl and C++
  7. level and shows how to move to-fro the Tcl and C++ boundaries. It also
  8. briefly covers memory debugging and memory conservation in ns.
  9. section{Tcl-level Debugging}
  10. label{sec:tcldebug}
  11. Ns supports Don Libs' Tcl debugger ( see its Postscript documentation at
  12. http://expect.nist.gov/tcl-debug/tcl-debug.ps.Z and its source code at
  13. http://expect.nist.gov/tcl-debug/tcl-debug.tar.gz ).
  14. Install the program or leave the source code in a directory
  15. parallel to ns-2 and it will be built. Unlike expect, described in the
  16. tcl-debug documentation, we do not support the -D flag. To enter the
  17. debugger, add the lines "debug 1" to your script at the appropriate
  18. location. In order to build ns with the debugging flag turned on,
  19. configure ns with configuration option "--enable-debug"
  20. and incase the Tcl debugger has been installed in a directory not parallel
  21. to ns-2, provide the path with configuration option 
  22. "--with-tcldebug=<give/your/path/to/tcl-debug/library>".
  23. An useful debugging command is code{$ns_ gen-map} which may be used to 
  24. list all OTcl objects in a raw form. This is useful to correlate the
  25. position and function of an object given its name. The name of the object
  26. is the OTcl handle, usually of the form code{_o###}. For TclObjects, this
  27. is also available in a C++ debugger, such as gdb, as code{this->name_}. 
  28. section{C++-Level Debugging}
  29. label{sec:cdebug}
  30. Debugging at C++ level can be done using any standard debugger. The
  31. following macro for gdb makes it easier to see what happens in Tcl-based
  32. subroutines: 
  33. begin{program}
  34. ## for Tcl code
  35. define pargvc
  36. set $i=0
  37. while $i < argc
  38.   p argv[$i]
  39.   set $i=$i+1
  40.   end
  41. end
  42. document pargvc
  43. Print out argc argv[i]'s common in Tcl code.
  44. (presumes that argc and argv are defined)
  45. end
  46. end{program}
  47. section{Mixing Tcl and C debugging}
  48. label{sec:mixdebug}
  49. It is a painful reality that when looking at the Tcl code and debugging
  50. Tcl level stuff, one wants to get at the C-level classes, and vice versa.
  51. This is a smallish hint on how one can make that task easier. If you are
  52. running ns through gdb, then the following incantation (shown below) gets
  53. you access to the Tcl 
  54. debugger. Notes on how you can then use this debugger and what you can do
  55. with it are documented earlier in this chapter and at this URL
  56. (http://expect.nist.gov/tcl-debug/tcl-debug.ps.Z).
  57. begin{program} 
  58. (gdb) run
  59. Starting program: /nfs/prot/kannan/PhD/simulators/ns/ns-2/ns 
  60. ...
  61. Breakpoint 1, AddressClassifier::AddressClassifier (this=0x12fbd8)
  62.     at classifier-addr.cc:47
  63. (gdb) p this->name_
  64. $1 = 0x2711e8 "_o73"
  65. (gdb) call Tcl::instance().eval("debug 1")
  66. 15: lappend auto_path $dbg_library
  67. dbg15.3> w
  68. *0: application
  69.  15: lappend auto_path /usr/local/lib/dbg
  70. dbg15.4> Simulator info instances
  71. _o1
  72. dbg15.5> _o1 now
  73. 0
  74. dbg15.6> # and other fun stuff
  75. dbg15.7> _o73 info class
  76. Classifier/Addr
  77. dbg15.8> _o73 info vars
  78. slots_ shift_ off_ip_ offset_ off_flags_ mask_ off_cmn_
  79. dbg15.9> c
  80. (gdb) w
  81. Ambiguous command "w": while, whatis, where, watch.
  82. (gdb) where
  83. #0  AddressClassifier::AddressClassifier (this=0x12fbd8)
  84.     at classifier-addr.cc:47
  85. #1  0x5c68 in AddressClassifierClass::create (this=0x10d6c8, argc=4, 
  86.     argv=0xefffcdc0) at classifier-addr.cc:63
  87. ...
  88. (gdb)
  89. end{program}
  90. In a like manner, if you have started ns through gdb, then you can always
  91. get gdb's attention by sending an interrupt, usually a code{<Ctrl-c>}
  92. on
  93. berkeloidrones. However, note that these do tamper with the stack frame, and on occasion,
  94. may (sometimes can (and rarely, does)) screw up the stack so that, you may
  95. not be in a position to resume execution. To its credit, gdb appears to be
  96. smart enough to warn you about such instances when you should tread
  97. softly, and carry a big stick. 
  98. section{Memory Debugging}
  99. label{sec:memdebug}
  100. The first thing to do if you run out of memory is to make sure you can use
  101. all the memory on your system. Some systems by default limit the memory
  102. available for individual programs to something less than all available
  103. memory. To relax this, use the limit or ulimit command. These are shell
  104. functions---see the manual page for your shell for details. Limit is for
  105. csh, ulimit is for sh/bash. 
  106. Simulations of large networks can consume a lot of memory. Ns-2.0b17
  107. supports Gray Watson's dmalloc library (see its web documentation at
  108. http://www.letters.com/dmalloc/ and get the source code from
  109. ftp://ftp.letters.com/src/dmalloc/dmalloc.tar.gz ).
  110. To add it, install it on your system or leave its source in
  111. a directory parallel to ns-2 and specify --with-dmalloc when configuring
  112. ns. Then build all components of ns for which you want memory information
  113. with debugging symbols (this should include at least ns-2, possibly tclcl
  114. and otcl and maybe also tcl). 
  115. subsection{Using dmalloc}
  116. label{sec:usedmalloc}
  117. In order to use dmalloc do the following:
  118. begin{itemize}
  119. item Define an alias 
  120. begin{verbatim}
  121. for csh: alias dmalloc 'eval `dmalloc -C !*`', 
  122. for bash: function dmalloc { eval `command dmalloc -b $*` }%$
  123. end{verbatim}
  124. item Next turn debugging on by typing code{dmalloc -l logfile low }
  125. item Run your program (which was configured and built with dmalloc as
  126. described above). 
  127. item Interpret logfile by running code{dmalloc_summarize ns <logfile}.
  128. (You need to download code{dmalloc_summarize} separately.) 
  129. end{itemize}
  130. On some platforms you may need to link things statically to get dmalloc to
  131. work. On Solaris this is done by linking with these options:
  132. code{"-Xlinker -B -Xlinker -static {libraries} -Xlinker -B -Xlinker -dynamic -ldl -lX11 -lXext"}.
  133. (You'll need to change Makefile. Thanks to
  134. Haobo Yu and Doug Smith for working this out.) 
  135. We can interpret a sample summary produced from this process on
  136. ns-2/tcl/ex/newmcast/cmcast-100.tcl with an exit statement after the
  137. 200'th duplex-link-of-interefaces statement: 
  138. Ns allocates ~6MB of memory. \
  139. ~1MB is due to TclObject::bind \
  140. ~900KB is StringCreate, all in 32-byte chunks \
  141. ~700KB is NewVar, mostly in 24-byte chunks \
  142. Dmalloc_summarize must map function names to and from their addresses. It
  143. often can't resolve addresses for shared libraries, so if you see lots of
  144. memory allocated by things beginning with ``ra='', that's what it is. The
  145. best way to avoid this problem is to build ns statically (if not all, then
  146. as much as possible). 
  147. Dmalloc's memory allocation scheme is somewhat expensive, plus there's
  148. bookkeeping costs. Programs linked against dmalloc will consume more
  149. memory than against most standard mallocs. 
  150. Dmalloc can also diagnose other memory errors (duplicate frees, buffer
  151. overruns, etc.). See its documentation for details. 
  152. subsection{Memory Conservation Tips}
  153. label{sec:memconserve}
  154. Some tips to saving memory (some of these use examples from the 
  155. cmcast-100.tcl script): 
  156. If you have many links or nodes: 
  157. begin{description}
  158. item[Avoid code{trace-all} :]
  159. code{$ns trace-all $f} causes trace objects to be pushed on all links. If 
  160. you only want to trace one link, there's no need for this overhead. Saving
  161. is about 14 KB/link. 
  162. item[Use arrays for sequences of variables :]
  163. Each variable, say code{n$i} in code{set n$i [$ns node]}, has a certain
  164. overhead. If a sequence of nodes are created as an array, i.e.
  165. code{n($i)}, then only one variable is created, consuming much less
  166. memory. Saving is about 40+ Byte/variable. 
  167. item[Avoid unnecessary variables :]
  168. If an object will not be referred to later on, avoid naming the object.
  169. E.g.
  170. code{set cmcast(1) [new CtrMcast $ns $n(1) $ctrmcastcomp [list 1 1]]}
  171. would be better if replaced by
  172. code{new CtrMcast $ns $n(1) $ctrmcastcomp [list 1 1]}.
  173. Saving is about 80 Byte/variable. 
  174. item[Run on top of FreeBSD :]
  175. malloc() overhead on FreeBSD is less than on some other systems. We will
  176. eventually port that allocator to other platofrms. 
  177. item[Dynamic binding :]
  178. Using bind() in C++ consumes memory for each object you create. This
  179. approach can be very expensive if you create many identical objects.
  180. Changing code{bind()} to code{delay_bind()} changes this memory
  181. requirement to per-class. See ns/object.cc for an example of how to do
  182. binding, either way.
  183. item[Disabling packet headers :]
  184. For packet-intensive simulations, disabling all packet headers that
  185. you will not use in your simulation may significantly reduce memory
  186. usage. See Section~ref{sec:ppackethdr} for detail.
  187.  
  188. end{description}
  189. subsection{Some statistics collected by dmalloc}
  190. label{sec:statdmalloc}
  191. A memory consumption problem occured in recent simulations 
  192. (cmcast-[150,200,250].tcl), so we decided to take a closer look at scaling
  193. issue. See page http://www-mash.cs.berkeley.edu/ns/ns-scaling.html
  194. which demostrates the efforts in finding the bottlneck. 
  195.  
  196. The following table summarises the results of investigating the
  197. bottleneck:\
  198. begin{table}[h]
  199. begin{center}
  200. begin{tabular}{|c|c|c|}hline  
  201. {em KBytes} &{em cmcast-50.tcl(217 Links)} &{em cmcast-100.tcl(950 
  202. Links)}\hline 
  203. trace-all &8,084 &28,541\hline
  204. turn off trace-all &5,095 &15,465 \hline
  205. use array &5,091 &15,459\hline 
  206. remove unnecessay variables &5,087 &15,451 \hline
  207. on SunOS &5,105 &15,484\hline
  208. end{tabular}
  209. end{center}
  210. end{table}
  211. section{Memory Leaks}
  212. label{memleak}
  213. This section deals with memory leak problems in ns, both in Tcl as well
  214. as C/C++.
  215. subsection{OTcl}
  216. label{leakTcl}
  217. OTcl, especially TclCL, provides a way to allocate new objects. However,
  218. it does not accordingly provide a garbage collection mechanism for these
  219. allocated objects. This can easily lead to unintentional memory leaks.
  220. Important: tools such as dmalloc and purify are unable to detect this kind
  221. of memory leaks. For example, consider this simple piece of OTcl script: 
  222. begin{program}
  223. set ns [new Simulator]
  224. for {set i 0} {$i < 500} {incr i} {
  225.         set a [new RandomVariable/Constant]
  226. }
  227. end{program}
  228. One would expect that the memory usage should stay the same after the
  229. first RandomVariable is allocated. However, because OTcl does not have
  230. garbage collection, when the second RandomVariable is allocated, the
  231. previous one is not freed and hence results in memory leak. Unfortunately,
  232. there is no easy fix for this, because garbage collection of allocated
  233. objects is essentially incompatible with the spirit of Tcl. The only way
  234. to fix this now is to always explicitly free every allocated OTcl object
  235. in your script, in the same way that you take care of malloc-ed object in
  236. C/C++. 
  237. subsection{C/C++}
  238. label{leakC}
  239. Another source of memory leak is in C/C++. This is much easier to track
  240. given tools that are specifically designed for this task, e.g., dmalloc
  241. and purify. ns  has a special target ns-pure to build purified ns
  242. executable. First make sure that the macro PURIFY in the ns Makefile
  243. contains the right -collector for your linker (check purify man page if
  244. you don't know what this is). Then simply type code{make ns-pure}. See
  245. earlier sections in this chapter on how to use ns with libdmalloc.