[ First ]  [ Previous ]  [ Next ]  [ Last ]  [ Manuals ]

 

Chapter 6.

 

Profiling in PowerPlant



The PowerPlant Profiler Class is a wrapper class for the Profiler API. It provides an easy to use interface for the initialization and termination functions of the profiler.


Introduction to Profiling in PowerPlant

If you have used the profiler before to profile C or Pascal code, you are already familiar with how the initialization and termination routines work. In PowerPlant, you never need to call these routines directly. Instead, these calls are handled for you by the constructor and destructor of the profiling class.

In this chapter, you'll learn:

There is a code exercise provided at the end of this chapter to give you a full working tutorial on how to use the profiler class in your PowerPlant programs.


Profiling Strategy

Before you delve into the depths of the Profiler Class, you should familiarize yourself with the profiler in general. We recommend that you read the Profiler Guide first to become familiar with all aspects of the profiler. Some information is reiterated here, but you should read the Profiler Guide for more in-depth information.

You use a profiler to measure the runtime performance of your code. What is usually important is how your code's performance measures up to some standard. When approaching the problem of measuring performance, you might want to take these three steps.

1. Establish your standards.

For example, you might decide that you want the program to load in less than ten seconds, or check the spelling of a five-page document that contains no misspellings in 15 seconds. Decide the platform you will use for testing as well: a Power Macintosh is a bit faster than a Mac Plus.

2. Determine how to measure time.

Your measurement device may be no more complicated than a stopwatch, or you may need to add some simple code to count ticks. At this phase you want to test the code in as close to its finished form as possible, so measure time in a way that is accurate enough to suit your needs, and that has the lowest impact on your code's natural performance. You do not want to run a full-blown profile here, because profiling can add significant overhead, thus slowing down your code's raw performance.

3. Run the tests and measure results.

If you meet your performance goals, your job is done. If your code does not meet your goals, then it's time to profile your code.


Rules of Thumb

To make sure you get a good profile of your code, there are few general rules of thumb you need to follow.

1. Turn off all optimizations

Optimization settings will cause skewed results in the profiler output. Part of the reason for profiling your code is so you can optimize it yourself as much as possible. Once you are confident you've done all you can, you can turn on optimizations in the final build of your application.

2. Turn off virtual memory or RAM Doubler

Profiling code with virtual memory or RAM Doubler active produces erratic and skewed result times. If your program runs quickly without virtual memory or RAM Doubler active, it will run quickly with them active.

3. Disable Speed Doubler

Speed Doubler is a performance enhancement series of extensions. As such, it will skew your result times and should therefore be disabled while profiling your code.


TIP

It's actually best to turn off all extensions when doing a profile of your code. This will eliminate any chances of extension problems and background tasks skewing the profile results. Restart your computer with the Shift key held down to disable extensions.


4. Do not use UnloadSeg() in 68K code

Calls to UnloadSeg() will cause garbage output when you look at your data with the MW Profiler application. Comment out, or remove calls to UnloadSeg() until the final build of your program.


Profiling Class

The PowerPlant profiler class is called StProfileSection and is found in UProfiler.cp. The "St" means that this is a stack-based class and functions accordingly. This class is an independent class and can therefore be used with or without the rest of PowerPlant.

StProfileSection makes two assumptions when calling Profiler-Init(). First, it uses collectDetailed as the data collection method. Second, it uses bestTimeBase for the timing method parameter. StProfileSection only has two member functions, a constructor and a destructor.

See Also "Profiler Function Reference" for more information on the parameters used for ProfilerInit().


StProfileSection

The class constructor takes three parameters and performs two main operations. It initializes three data members with the values you provide, and calls ProfilerInit() using these values. The constructor is declared as follows:


StProfileSection( Str255 inDumpFileName, 
SInt16 inNumFunctions,
SInt16 inStackDepth);


TIP

If you are profiling your entire PowerPlant program, you should use large values for inNumFunctions and inStackDepth. The values you use will depend on the size of your program. For example, use 2500 for inNumFunctions and 100 for inStackDepth to start, then increase either of these values if necessary after each profile run. Also, remember it may become necessary to increase the memory size of your application program as profiling takes more memory than would normally be required.


The three data members are shown in Table 6.1.

StProfileSection data members:

 

Data Member
Stores
mProfilerDumpFile  
pascal string for the dump filename  
mNumFunctions  
number of routines to create buffer space for  
mStackDepth  
number of routines deep the stack can get  


~StProfileSection

~StProfileSection() is the class destructor. It is called automatically as soon as the code you are profiling goes out of scope. If you are profiling one area of your code, it's when that function ends. If you are profiling your entire application, it's when the application quits.

The destructor does all the house cleaning work. It calls ProfilerSetStatus() to stop profiling while it performs the clean up, calls ProfilerGetDataSizes() to test memory requirements and sends an Assert_() if there wasn't enough memory, calls ProfilerDump() to dump the results to the file, and finally, calls ProfilerTerm() to end the profile session.


NOTE

If you get an Assert_() message, it means the values you provided for inNumFunctions and inStackDepth are too low. You will need to re-profile your code using larger values.



Profiling Your Code

To profile your code, you do four things.

1. Set up your project for profiling

This step is very similar to the description given in the Profiler Guide. The only changes are the source file you add to your project, and the header file you add to your code. More detail on this is given in the code exercise.

2. Run a profiler on the area of the code you want tested.

This might be a single routine, a group of routines that perform a task, or even the entire application. What you profile depends upon what you are testing.

Declare a local StProfileSection variable, and provide the proper setup information. Your declaration will look something like this:


  StProfileSection theProfile("\pTest", 50, 50);

All code that runs from that point on, until theProfile goes out of scope, will be profiled.

3. Analyze the data collected by the profiler and improve your code.

You study the results of your profiling and look for problems and room for improvement. For details on how to review the results, see "Viewing Results."

The profiling process is iterative. You repeat steps 2 and 3 until you achieve the performance gain you need to meet your goals.

4. Run your code without the profiler

When you are satisfied that you have reached your goals, you have one more step to perform. You should run your original tests-without the profiler of course-to verify that your code in its natural state meets your performance goals.

Implementing the above steps in your program is simple and only requires two lines of code.


Code Exercise for Profiling

This code exercise uses the Documents solution code from the File
I/O chapter of The PowerPlant Book. The code can be found on the CodeWarrior Reference CD, in the CodeWarrior Examples: MacOS Examples:PP Book Code:Chap 13 Solution Code folder.


WARNING!

It is important for this exercise that you use the Solution code for the Documents application. Using the Starter Code will either not compile, or crash when run, unless you have finished it in the exercise in The PowerPlant Book.


In this exercise you will perform two different profiles. The first profile will only focus on one routine (and any routines it calls). The second profile will be the entire application. The steps for each are similar.


Profiling a Single Routine

There is one important thing to remember when you want to profile a single routine. You are also profiling all other routines called directly or indirectly by the routine being profiled. This is important in order to provide the correct parameters to the constructor. This part of the code exercise will profile the OpenFile() routine in CTextDocument.cp.


WARNING!

When you are profiling a single routine, you must declare your StProfileSection variable in the function that calls the routine you want to profile. If you declare an StProfileSection variable inside the function you want to profile, you will not see the name of your routine in the MW Profiler application. Your routine would still be profiled, but you would be missing an important point of reference in the resulting data.


1. Set up the project for profiling

There are two things you need to do for this step. You can do these in any order you wish. First, add the necessary source and library files to your project. Then turn on profiling from the preference panel. These steps are the same for both 68K and PowerPC projects.

a. Adding files to the project

Add UProfiler.cp to your project as well as the appropriate library. The library you add depends on the type of program you are writing and your target platform (68K or PowerPC). Table 6.2 lists the libraries and shows you when to use them.

Profiler libraries:

 

Library
Processor
When To Use
Profiler 68k.Lib  
68K (A5 globals)  
near/small model applications  
Profiler Fa(68k).Lib  
68K (A5 globals)  
far/large/smart model applications  
Profiler 68k.A4.Lib  
68K (A4 globals)  
near/small model code resources  
Profiler Fa(68k.A4).Lib  
68K (A4 globals)  
far/large/smart model code resources  
Profiler CFM68k.Lib  
68K (A5 globals)  
code fragments and shared libraries  
Profiler PPC.Lib  
PowerPC  
PowerPC applications and shared libraries  
Profiler PPC.MP.Lib  
PowerPC  
PowerPC multiprocessor applications and shared libraries  
ProfilerMPLib  
PowerPC  
PowerPC multiprocessor code fragments and shared libraries.  
ProfilerLib  
CFM 68K & PowerPC  
code fragments and shared libraries  
Profiler Carbon.Lib  
PowerPC (Carbon)  
PowerPC applications and shared libraries for use on Mac OS X or Mac OS 8.1 and above with the Carbon libraries  
ProfilerCarbonLib  
PowerPC (Carbon)  
PowerPC code fragments and shared libraries for use on Mac OS X or Mac OS 8.1 and above with the Carbon libraries  

The example shown in Figure 6.1 uses ProfilerPPC.lib for this exercise.

See Also "Profiler Libraries and Interface Files" for more information on profiler libraries.

Adding profiler files to the project:

b. Turn on profiling for the project

Select Profiler Information from the PPC Processor preference panel as shown in Figure 6.2Figure 6.2.

Generate profiler calls:

2. Add the header file

CTextDocument.cp

You need to include UProfiler.h in the file that makes the call to the StProfileSection class. It is not needed in any other file in your project even if the routine your profiling calls routines in a different file.

  #include <UProfiler.h>

3. Declare an StProfileSection variable

CTextDocument() CTextDocument.cp

In order to profile the routine you want, you declare the StProfileSection variable in the routine that makes the call to the function you are concerned with. In this case, you put the declaration in the class constructor right before the call to OpenFile().


  // Set name of window or open file.   if ( inFileSpec == nil ) {
  
   NameNewDoc();
  
  } else {
   // Profile the OpenFile routine
   StProfileSection theProfile("\pTest", 50, 50);
   OpenFile( *inFileSpec );
  

}

4. Build and run the application

That's all there is to it! Once the application builds successfully, run the application, open a file, then quit. There will be a file called "Test" in the same folder as the application. You can then use the MW Profiler application to view the results.

See Also "Viewing Results" for more information on how to view your data.


Profiling an Application

You might decide you want to get the "big picture" of what's happening in your code. To do that, you would profile your entire PowerPlant program.

The steps you perform are exactly the same as shown above with the exception of steps two and three. If you've performed the above tasks, remove the header file and the declaration of StProfileSection and replace them with the following steps.

1. Add the header file

CDocumentsApp.cp

Add the header file to the top of CDocumentsApp.cp.

  #include<UProfiler.h>

2. Declare the StProfileSection variable

main() CDocumentsApp.cp

You do not necessarily need to profile the initialization code unless you feel it is a concern. The code below declares the class before the Run() command is given. You may put it at the top of main() if you wish.


  // Create the application object and run it.   CDocumentsApp theApp;
  StProfileSection theProfile("\pApp", 2500, 100);

theApp.Run();

3. Build and run the application

That's all there is to it! Once the application builds successfully and runs, a complete profile of the application will be built. You have to quit the application for the StProfileSection class to go out of scope, write the data, and close the file. Once you've done that, there will be a file called "App" in the same folder as the application. You can then use the MW Profiler application to view the results.


TIP

If you run multiple profiles of your code, the profiler routines are smart enough not to overwrite the same dump file. Instead, it will append a number after the file name (e.g.: App2). This is useful if you want to compare different profiles of your program (as you make changes) and not have to change your code. For example, you may want to compare the 68K version with the PowerPC version. For reliable comparisons, make sure you profile exactly the same routines each time, and in each version.


See Also "Viewing Results" for more information on how to view your data.

 

 


[ First ]  [ Previous ]  [ Next ]  [ Last ]  [ Manuals ]

Visit the Metrowerks website at: http://www.metrowerks.com
For assistance contact Metrowerks Technical Support at: cw_support@metrowerks.com
Copyright © 2000, Metrowerks Corp. All rights reserved.

Last updated: July 21, 2000