Friday, November 16, 2007

Profiling Perl with Compuware BoundsChecker

I finally got around to trying out the Perl core under BoundsChecker. Because Perl does not have an MSVC project file, it was a bit tougher than many Visual C++ programs.

Fortunately, BoundsChecker does support command line profiling, albeit it is nowhere as easy as their graphical interface for setting up instrumentation (as would be expected).

Change the CC and LINK32 lines in Win32/Makefile to refer to "nmcl" and "nmlink" instead of "cl" and "link":

#
# Programs to compile, build .lib files and link
#
#BUILDOPT = $(BUILDOPT)
#CC = cl
CC = nmcl /NMtxOn
#LINK32 = link
LINK32 = nmlink /NMtxOn
LIB32 = $(LINK32) -lib
RSC = rc

Note that in the above case, I also added "/NMtxOn" to enable performance profiling as opposed to error checking. If you are just interested in errors, you can exclude that option (but be sure to exclude it for both CC and LINK32 or else you get some nasty errors).

Also uncovered a edge case where Perl does not build XS modules properly if using BoundsChecker. This is related to the way ExtUtils determines which compiler you are using. Because BoundsChecker relies on wrapping "cl.exe" around its own binary (called nmcl.exe), changing the CC directive in the makefile interferes with the compiler detection in Perl. Unfortunately, this manifests itself not as an error in determining the compiler but rather as a failure to setup EXTRALIBS and LDLOADLIBS properly.

The fix is to add a update lib/ExtUtils/LibList/Kid.pm to treat both cl.exe and nmcl.exe as being Visual C++.

diff.exe -u Kid.pm.orig Kid.pm
--- Kid.pm.orig 2005-10-21 07:44:36.000000000 -0400
+++ Kid.pm 2007-11-16 11:03:42.664799500 -0500
@@ -227,7 +227,7 @@
return ("", "", "", "", ($give_libs ? [] : ())) unless $potential_libs;

my $cc = $Config{cc};
- my $VC = $cc =~ /^cl/i;
+ my $VC = $cc =~ /^cl/i || $cc =~ /^nmcl/i;
my $BC = $cc =~ /^bcc/i;
my $GC = $cc =~ /^gcc/i;
my $so = $Config{'so'};

Once I did the above, I was able to generate profiles for Perl:

"c:\program files\compuware\devpartner studio\analysis\dpanalysis.exe" /perf /O c:\perl\bin\foo.dpprf /EXCLUDE_SYSTEM_DLLS /p perl foo.pl

Note that if you do not include the "/EXCLUDE_SYSTEM_DLLS", you will get errors saying "Unable to locate winsock library!"

To do error checking I used:

"c:\program files\compuware\devpartner studio\boundschecker\bc.exe" /b foo3.DPbcl perl foo.pl


Here is a pretty snapshot of a performance profile (click on it to expand):