monograph is a tool that Paolo developed; it generates the raw data that graphviz uses to generate the images. (monograph is included in current mono release.) After I started working with Rotor, Microsoft's shared source CLI, I thought it would be fun to use monograph to peruse Rotor's base class libraries. I got sidetracked by some other projects, and went a while without having the latest version of Mono on my system. However, the O'Reilly Emerging Technology Conference is rapidly approaching, and I wanted to make sure I have a comprehensive assortment of ECMA CLI implementations on my laptop. So, I set up three partitions: the latest beta of Windows .NET Web Server with Visual Studio .NET, FreeBSD 4.5 with Rotor, and Mandrake 8.2 with Mono (to build Mono, the only things I needed to add to the stock install of Mandrake 8.2 were glib 2.0.1 and pkg-config, both of which I installed in /opt). I still have yet to install DotGNU Portable.NET, but it won't be long before I add this to my assortment.
After I had Rotor and Mono built and running, I downloaded and installed graphviz on my Linux system. Then, I copied Rotor's mscorlib.dll and System.dll over to my Linux partition. Now, everything was in place for my sinister experiments. First, I generated a call graph for System.Net.WebClient.DownloadData():
[bjepson@localhost RotorDLLs]$ monograph -n -o example.ps -c \ ./System.dll System.Net.WebClient:DownloadData
Note that I prefixed the DLL name with ./ to explicitly
specify the Rotor DLL I had copied over. Otherwise, monograph might
have picked up Mono's System.dll. The figure I got was convoluted, so I tried limiting the recursion
depth with -d 1:
[bjepson@localhost RotorDLLs]$ monograph -d 1 -n -o example.ps -c \ ./System.dll System.Net.WebClient:DownloadData
Figure 1 shows a thumbnail of the output. Click on the thumbnail to see a larger version.
Since monograph generates an intermediate textual representation of
the call graph, I thought it would be interesting to compare two
implementations of the same method. So, I removed the -n
option, which automatically invoked the graphviz neato command, and specified a method that wasn't quite as big as the previous example. This
leaves me with two text documents, mono.txt and rotor.txt:
[bjepson@localhost RotorDLLs]$ monograph -d 1 -o rotor.txt -c \ ./mscorlib.dll System.Collections.Hashtable:Add [bjepson@localhost RotorDLLs]$ monograph -d 1 -o mono.txt -c \ /opt/lib/corlib.dll System.Collections.Hashtable:Add
As you can see, the implementations are quite different (I removed the
Hashtable: prefix from Hashtable's methods to minimize
annoying HTML wrapping problems):
mono.txt:
digraph blah {
node [fontsize=8.0]
edge [len=2,color=red]
"Add(object,object)" -> "Hashtable:PutImpl(object,object,bool)"
"PutImpl(object,object,bool)" -> "ArgumentNullException:.ctor(string)"
"PutImpl(object,object,bool)" -> "Rehash()"
"PutImpl(object,object,bool)" -> "GetHash(object)"
"PutImpl(object,object,bool)" -> "KeyEquals(object,object)"
"PutImpl(object,object,bool)" -> "ArgumentException:.ctor(string)"
}
rotor.txt:
digraph blah {
node [fontsize=8.0]
edge [len=2,color=red]
"Add(object,object)" -> "Hashtable:Insert(object,object,bool)"
"Insert(object,object,bool)" -> "Environment:GetResourceString(string)"
"Insert(object,object,bool)" -> "ArgumentNullException:.ctor(string,string)"
"Insert(object,object,bool)" -> "expand()"
"Insert(object,object,bool)" -> "InitHash(object,uint,int&,int&)"
"Insert(object,object,bool)" -> "KeyEquals(object,object)"
"Insert(object,object,bool)" -> "Environment:GetResourceString(string,object[])"
"Insert(object,object,bool)" -> "ArgumentException:.ctor(string)"
"Insert(object,object,bool)" -> "BCLDebug:Assert(bool,string)"
"Insert(object,object,bool)" -> "InvalidOperationException:.ctor(string)"
}
Figure 2 shows the two call graphs.
The beauty of monograph is that you can use it with an assembly from any of the ECMA CLI implementations. Given that these implementations are huge, it's helpful to have a visualization tool that can turn complex relationships into understandable pictures.
Brian Jepson is an O'Reilly editor, programmer, and co-author of Mac OS X Panther for Unix Geeks and Learning Unix for Mac OS X Panther. He's also a volunteer system administrator and all-around geek for AS220, a non-profit arts center in Providence, Rhode Island. AS220 gives Rhode Island artists uncensored and unjuried forums for their work. These forums include galleries, performance space, and publications. Brian sees to it that technology, especially free software, supports that mission. You can follow Brian's blog here.
oreillynet.com Copyright © 2006 O'Reilly Media, Inc.