Profiler Use Cases

Analyzer ›› Profiler Concepts ››
Parent Previous Next

Table of Contents

1        Profiler Use Cases        2

1.1        Execution Profiling        2

1.2        RTOS Profiling        5

1.3        OTM profiler        10

1.4        RTOS Profiling on an ICE configuration        15




22Profiler Use Cases

22.1Execution Profiling

An application is profiled to get an overview on how much time the CPU spends in each C function.

Open the Analyzer Configuration dialog by pressing the Analyzer Configuration icon in the Analyzer toolbar.

Analyzer Configuration is by default configured  to provide Profiler analysis:

Open the Profiler tab. Code profiler is enabled by default. Click New in the Core Areas region and select the functions you wish to profile:

Select function main for the start point or keep it blank, which yields start as soon as the application is running and the profiler is started.

Reset the system, start the profiler and run the application. Profiler stops recording after the trace buffer fills up or the program is stopped and then displays the results. Let’s inspect the profiler results.

Open the statistics pane:

Click on a specific function (e.g. dummyFunction in our example) in the profiler window and select ‘Properties’ from the local menu to obtain all the profiler details for this particular function.


When it’s necessary to obtain more details about behavior within a profiled function (for instance, in which source line or part of the function the CPU spends most of the time), include source lines when adding a function to the profiled areas.

Note: more profiler areas defined incurs more processing overhead. On an ICE system, this will also reduce the total session time due to the limited trace buffer depth.

22.2RTOS Profiling

The target application runs an operating system. Profile should measure tasks and all functions.

First setup RTOS awareness:

oFor RTOS available as plugin (FreeRTOS,  rcX RTOS…) load the desired RTOS plugin in Plugins/Options dialog. Kernel objects are already chosen to be recorded by default.

oFor Autosar, uC/OS-II and other set up the OS awareness in Debug/Operating System dialog and click Setup to configure OS specific settings. Read more about the settings in the RTOS help topic.

Select ‘Code’ and ‘OS objects’ in the Profiler Configuration dialog.

Click OS Setup… to select the objects to be recorded.

Run the Analyzer and the application

Press Show Data toolbar button in Statistics and Timeline view to see task information.

22.3OTM profiler

Data profiler will be configured to obtain functions profiler results on Freescale MPC5xxx development system, which features no data trace but features an ownership trace (OTM). This profiler technique requires code instrumentation of the target application.

Create new Profiler session in the Analyzer window and open Profiler Configuration dialog.

Check the ‘Data’ check box and uncheck the other check boxes in the ‘Profile’ field.

Press the ‘New…’ button next to the Data Areas to open the Profiler Data Area dialog.

Name a data object OTM Profiler.

Select ‘#define file’ option from the combo box and specify the define file in the ‘Value alias definition’ field. It’s assumed that define file is written prior to this step.

Per default, the values that the data object assumes will be shown verbatim in the profiler window. If the definitions for these values are provided in the define file, the more descriptive form is displayed in the profiler window. In this example, OTMDefs.h describes possible OTR values. The excerpt from the OTMDefs.h:

#ifndef __OTMDefs_h__

#define __OTMDefs_h__
#define fn_main                1

#define fn_mainExit                0

#define fn_Type_Simple        2

#define fn_Type_SimpleExit        0

#define fn_Type_Arrays        3

#define fn_Type_ArraysExit        0

#define fn_Type_Pointers        4

#define fn_Type_PointersExit        0

#endif 

A data object serves as an indicator of function/service entries and exits. Select ‘Area entry/exit ident by Zero’ option in the ‘Interpretation’ combo box. In this case, the data object value 0 indicates that the function has exited. All profiled functions should write zero to the data object (OTR) on exit. The profiler assumes which function exited on recorded 0 by knowing previously recorded entry point.

Close the ‘Profiler Data Area’ dialog. The profiler is now configured.

Next, the application source code must be modified. For all profiled functions, function entry and exit points must be instrumented with a write to the OTR. OTR, used later in the source code, is defined in the following way (valid for Freescale MPC5xxx microcontrollers):

void OTR(int msg)
{
 asm("mtmsr r3");
 asm("mtspr 48,r3");
}

Below is an excerpt of the modified example application code:

void main()

{

   OTR(fn_main);

    ...

    Type_Simple();

   Type_Arrays ();

   Type_Pointers ();

    ...

   OTR(fn_mainExit);

}

 

void Type_Simple()

{

   OTR(fn_Type_Simple);

    ...

    ...

   OTR(fn_Type_SimpleExit);

}

 

void Type_Arrays ()

{

   OTR(fn_Type_Arrays);

    ...

    ...

   OTR(fn_Type_ArraysExit);

}


void Type_Pointers ()

{

   OTR(fn_Type_Pointers);

    ...

    ...

   OTR(fn_Type_PointersExit);

}

Note that only functions to be profiled have to be instrumented. Finally, the profiler can be run.

Press ‘Show Data’ toolbar for OTM profiler results.

Let’s see the differences if the OTR is replaced by a global variable. Configure a new data object, which is a byte variable called m_byProfilerID. Next picture depicts the settings, which yields profiling m_byProfilerID variable.

All writes to the OTR in our source code should be now replaced with writes to the m_byProfilerID. Below is an example of main function writing to the global variable (e.g. m_byProfilerID) instead to the OTR.

void main()

{

   byProfilerID=otrMainEntry;

    ...

 

    ...

    Type_Simple();

    ...

   Type_Arrays ();

   Type_Pointers ();

    …

   byProfilerID=otrMainExit;

}


Now the profiler can be run and the results analyzed as before.

22.4RTOS Profiling on an ICE configuration

This example is very similar to the example 3 since the same concept is used but on an in-circuit emulator. Typically, an in-circuit emulator features functions profiler by default. Still, in this example, the data profiler is configured to obtain the functions profiler results on NEC V850ES/Fx3 ActivePRO development system.

This same approach can also be used to profile custom events in the application. For instance, the user first identifies custom events (e.g. check points) in the program and then equips those with extra code writing to a global variable. The data profiler can then profile that global variable and the user gets insight into the events’ behaviour respectively application behaviour.

Create new Profiler session in the Analyzer window and open Profiler Configuration tab.

Check the ‘Data’ check box and uncheck the other check boxes in the ‘Profile’ field.

Press the ‘New…’ button next to the Data Areas to open the Profiler Data Area dialog.

Put a name (e.g. Program Profiler) in the Description field and specify the name of the variable to which the instrumented application will write on function entry and exit (e.g. dwFunctionID).

Select ‘#define file’ option from the combo box and specify the define file in the ‘Value alias definition’ field. It’s assumed that the define file is written prior to this step.

Per default, values that the data object assumes will be shown verbatim in the profiler window. If the definitions for these values are provided in the define file, the more descriptive form is displayed in the profiler window. In this example, FunctionID.h describes possible m_ dwFunctionID global variable values. Below an excerpt from the FunctionID.h:

#define fn_Address_DifferentFunctionParameters   1

#define fn_Address_GlobalVariables   2

#define fn_Address_TestScopes   3

#define fn_Func1   8

#define fn_Func2   9

#define fn_Func3   10

#define fn_Type_Mixed   21

#define fn_Type_Pointers   22

#define fn_Type_Simple   23

#define fn_Type_Struct   24

#define fn_main   39

It is recommended that the application is modified in a way, that the added code is compiled and linked into the application conditionally. That means that the original unmodified application can still be easily tested too by simply commenting for instance one #define. Let’s assume that we define Profiler.h header file, which is then included in the main.c. The excerpt from the Profiler.h:

#ifndef __Profiler_h__

#define __Profiler_h__


#define PROFILER_ENABLE

#define PROFILER_TYPE long


#ifdef PROFILER_ENABLE

#include "ProfilerFuncs.h"

extern PROFILER_TYPE g_ProfilerID;


#define PROFILER_ENTRY(FN_NAME)        g_ProfilerID=FN_NAME;

#define PROFILER_EXIT                          g_ProfilerID=0;


#else  /* PROFILER_ENABLE */

#define PROFILER_ENTRY(FN_NAME)

#define PROFILER_EXIT


#endif /* PROFILER_ENABLE */

#endif /* __Profiler_h__ */


Now, as long as the application needs to be instrumented for debugging needs, set

#define PROFILER_ENABLE

in the Profiler.h. When performing the final application test or when functions profiler via data profiler is no longer required, simply comment the define

// #define PROFILER_ENABLE

and recompile the project, which results in the original application code without instrumentation.

A data object dwFunctionID serves as an indicator of function/service entries and exits. Select ‘Area entry/exit ident by Zero’ option in the ‘Interpretation’ field. In this case, the data object value 0 indicates that the function has exited. All profiled functions should write zero to the dwFunctionID data object on exit. The debugger can assume which function exited on recorded 0 by examining previously recorded entry point. Note that this concept works always as long as all functions writing 0 on exit are profiled.

Close the Profiler Data Area dialog. The profiler is now configured.

In final step, the original source code must be instrumented. For all profiled functions, entry and exit points must write to the m_dwFunctionID global variable. Below is an example of the instrumented source:

void main()

{

   PROFILER_ENTRY(fn_main);

    ...

    Type_Simple();

   Type_Arrays ();

   Type_Pointers ();

    ...

   PROFILER_EXIT

}

 

void Type_Simple()

{

    PROFILER_ENTRY(fn_Type_Simple);

    ...

    ...

    PROFILER_EXIT

}

 

void Type_Arrays ()

{

    PROFILER_ENTRY(fn_Type_Arrays);

    ...

    ...

    PROFILER_EXIT

}


void Type_Pointers ()

{

    PROFILER_ENTRY(fn_Type_Pointers);

    ...

    ...

    PROFILER_EXIT

}

 
Note that only functions, which are profiled, have to be instrumented. Finally, run the profiler and inspect the results.























Disclaimer: iSYSTEM assumes no responsibility for any errors which may appear in this document, reserves the right to change devices or specifications detailed herein at any time without notice, and does not make any commitment to update the information herein.

© iSYSTEM . All rights reserved.