Walkthrough: Using Profile-Guided Optimizations

This walkthrough demonstrates how to use profile-guided optimization (PGO) for varied scenarios that range from simple implementations using PGO build menus in the Visual Studio Integrated Development Environment (IDE), to more advanced scenarios that require custom configurations. This walkthrough also discusses advanced techniques that enable you to use PGO command line tools to customize the process for collecting and merging the profiling data. For overview information, see Profile-Guided Optimizations.

Building an Application with PGO

This example scenario illustrates how to build a simple application using PGO.

Building with PGO in the IDE

Profile guided optimizations can be applied on any native Visual C++ project. The following procedures illustrate using PGO with a Win32 application.

To create a Win32 project

  1. On the File menu, select New, and then select Project. The New Project dialog box appears.

  2. In the Project Types pane, select the Visual C++ node, and then in the Templates pane, select Win32 Project.

  3. In the Name box, enter PGODemo.

  4. Click the OK button. The Win32 Application Wizard appears.

  5. Keep all default settings. Click the Finish button.

To build the PGODemo project with PGO

  1. In the Standard toolbar, click the Solution Configuration combo box and select the Release configuration.

  2. In Solution Explorer, right-click the PGODemo project node. In the project context menu, select Profile Guided Optimization, and then select the Instrument menu item.

  3. In Solution Explorer, right-click the PGODemo project node. In the project context menu, select Profile Guided Optimization, then select Run Instrumented/Optimized Application to launch your application.

    Note

    You can also launch the instrumented application by selecting Start or Start Without Debugging from the Debug menu.

  4. Repeat step 3, to train the instrumented application using different scenarios. When an instrumented application shuts down, a .PGC file is created in the project output directory, which contains the profile data for that run.

  5. In Solution Explorer, right-click the PGODemo project node. In the project context menu, select Profile Guided Optimization, then select Optimize.

Building with PGO at the Command Line

Assume you want to build an application myapp.exe from the source files S1,…,Sn, using PGO optimization. First step is to make sure you compile your sources S1,…,Sn using the /GL compiler option.

You need also to specify the optimization options that matches your needs, let’s say you choose the /O2 option. It is to be mentioned that building your application with PGO but without any optimization options, i.e. using /Od, will fire a warning and the compiler will switch automatically to build for LTCG. From the command line your first step would be as follows:

To compile source files with /GL

  1. cl.exe /c /GL /O2 S1.cpp … Sn.cpp

  2. link /ltcg:pgi S1.obj … Sn.obj /out:myapp.exe

Step 2 creates a PGO instrumented image myapp.exe and also creates myapp.pgd which is the profile database file that will be used by the compiler to build the final optimized myapp.exe. The default name of the .pgd file is the name of the application and the default path is the output path.

You can use linker option /pgd in the previous step to change the default name of the .pgd file generated for your application. You can use /pgd as follows:

To create an instrumented image with /LTCG:PGI and /PGD

  • link /ltcg:pgi /pgd:mypgd.pgd S1.obj … Sn.obj /out:myapp.exe

Now you are ready to train the instrumented myapp.exe using your profiling scenarios. After you are done running the scenarios you will find a .pgc file created per run.

Note

If you run more than one image of myapp.exe from the same path simultaneously only one .pgc file will be created for all of them and this file will be written to the disk only after all instances are shut down.

Note

The default path for the .pgc files is the executable path. You can change this by setting the environment variable VCPROFILE_PATH before running your profiling scenarios. i.e. set VCPROFILE_PATH=<some path> then run your instrumented image myapp.exe

You are ready now to build the PGO optimized myapp.exe.

To create an optimized image with /LTCG:PGO and /PGD

  • link /ltcg:pgo /pgd:mypgd.pgd S1.obj … Sn.obj /out:myapp.exe

Note

Before step 1, you need to have all .PGC files created during the training scenario in the same folder as the profile database file (.PGD)

Custom Profile Data Merge

Let’s assume you have two main customer scenarios for your application. The first scenario is twice as important - or frequently done by customers - as the second one.

In the following steps you will learn how to use the Visual Studio development environment and the command line tools to give some profile data higher weight while merging it into the .PGD file.

Merging Profile Data in the IDE

To create a Win32 project

  1. On the File menu, select New, and then select Project. The New Project dialog box appears.

  2. In the Project Types pane, select the Visual C++ node, and then in the Templates pane, select Win32 Project.

  3. In the Name box, enter PGODemo.

  4. Click the OK button. The Win32 Application Wizard appears.

  5. Keep all default settings. Click the Finish button.

To build PGODemo project with merged profile data in the IDE

  1. In the standard toolbar, click the Solution Configuration combo box and choose the Release configuration.

  2. In the Solution Explorer, right click on the PGODemo project. Click Profile Guided Optimization form the shortcut menu, and then click Instrument.

  3. In the Solution Explorer, right click on the PGODemo project. Click Profile Guided Optimization from the shortcut menu, and then click Run Instrumented Application. This will launch your application. Note that you can also launch the instrumented application using the Start or Start Without Debugging from the Debug menu as normal.

  4. Repeat step 3 twice, once for each of your customer scenarios. This step will create two .PGC files in the output directory: PGODemo!1.pgc and PGODemo!2.pgc.

  5. In the Solution Explorer, right click on the PGODemo project. Click Properties, the PGODemo property pages dialog appears.

  6. In Configuration properties click Build Events then click Pre-Link Event. In the Command Line, type the following command:

    "$(VCInstallDir)bin\pgomgr.exe" -merge:2 $(OutDir)\$(ProjectName)!1.pgc $(OutDir)\$(ProjectName).pgd

    Note

    This step will use pgomgr.exe to merge PGODemo!1.pgc in a separate step before launching the linker to build the final optimized application. The linker will call pgomgr.exe again during the next step to merge PGODemo!2.pgc file but with the default weight of 1.

  7. In the Solution Explorer, right click on the PGODemo project. Click Profile Guided Optimization from the shortcut menu, and then click Optimize.

Merging Profile Data from the Command Line

You can use the command line tools to perform custom profile data merge as follows.

To build merged profile dated from the command line

  1. cl.exe /c /GL /O2 S1.cpp … Sn.cpp

  2. link /ltcg:pgi S1.obj … Sn.obj /out:myapp.exe

    The previous two steps will create the instrumented myapp.exe.

  3. Train the instrumented myapp.exe using two different scenarios will create two different .PGC files myapp!1.pgc and myapp!2.pgc.

    To give the first scenario higher weight use pgomgr.exe as follows:

    Pgomgr –merge:2 myapp!1.pgc myapp.pgd

  4. Run the link command to create the final optimized application as follows

    link /ltcg:pgo /pgd:myapp.pgd /out:myapp.exe

    This will merge myapp!2.pgc with the default weight of 1.

PGO Update

In the previous two scenarios we used the /ltcg:pgo linker option to build the final optimized application after building and training the instrumented. When using /ltcg:pgo option, the linker will perform some checks to make sure that no changes happened to the input files (object files, libraries, etc.) used to build the instrumented application. In other words, to use /ltcg:pgo, all input files passed to the linker must be the same as the files passed in the /ltcg:pgi step.

This is because accidental changes to the sources after building the instrumented application and the .PGD file can dramatically affect PGO code generation and optimization decisions.

Assume that after you built the instrumented application, created the profile data and built the PGO optimized application, you discovered that you forgot to update the version number of your application, or, you discovered a trivial bug which needs a very tiny fix that does not dramatically affect the flow in the application. For this scenario we have the /ltcg:pgu option. Using this option the linker will not perform the checks it does when using /ltcg:pgo option. You can edit and recompile files or even add new files to the application between PGI and PGU builds.

In the following steps you will learn how to use the Visual Studio development environment and the command line tools to use the /ltcg:pgu option.

Update in the IDE

To build PGODemo with /LTCG:PGU in the IDE

  1. In the standard toolbar, click the Solution Configuration combo box and choose the Release configuration.

  2. In the Solution Explorer, right click on the PGODemo project. Click Profile Guided Optimization form the shortcut menu, and then click Instrument.

  3. In the Solution Explorer, right click on the PGODemo project. Click Profile Guided Optimization from the shortcut menu, and then click Run Instrumented/Optimized Application. This will launch your application. Note that you can also launch the instrumented application using the Start Debugging or Start Without Debugging from the Debug menu as normal.

  4. In this step you can apply any changes to any source file. As mention above, changes that dramatically affect the behavior of your application can cause severe performance regressions. In general you would make very tiny changes, like small bug fixes or resource files changes.

  5. In the Solution Explorer, right click on the PGODemo project. Click Profile Guided Optimization from the shortcut menu, and then click Update. This will recompile the changed files only and then launch the linker with /ltcg:pgu option instead of /ltcg:pgo, allowing edited files

    Note

    You will get warnings for each new function that does not have profile data and each function edited in a way that invalidates the profile data collected during the training step. In the standard toolbar, click the Solution Configuration combo box and choose the Release configuration.

    Note

    In step 5 if you right click on the changes source file in the Solution Explorer and click Compile, this will delete all PGO related files in the output folder because the project system performs a clean build when you move from PGO build to a normal build.

Update at the Command Line

You can use the command line tools to perform the PGO update as follows.

To build with /LTCG:PGU at the command line

  1. cl.exe /c /GL /O2 S1.cpp … Sn.cpp

  2. link /ltcg:pgi S1.obj … Sn.obj /out:myapp.exe

    The previous two steps will create the instrumented myapp.exe.

  3. Train the instrumented myapp.exe

  4. link /ltcg:pgo /pgd:myapp.pgd /out:myapp.exe

    Step 4 will create the optimized myapp.exe. Assume that you found a small bug in Sm.cpp, you can apply the fixes and compile only Sm.cpp as follows

  5. cl /c /GL /O2 Sm.cpp

    Then use /ltcg:pgu to build the optimized application using the old profile data created in step 3.

  6. link /ltcg:pgu /pgd:myapp.pgd /out:myapp.exe

Custom PGO Configurations

In this scenario you will learn how to create custom PGO configurations to build solutions with multiple projects. In this scenario we will add a DLL to the solution and link it to PGODemo application. We will create two configurations: PGIRelease and PGORelease and use them to build the whole solution instead of using the Profile Guided Optimization menu items to build each product at a time.

To create custom PGO configurations

  1. On the File menu, select New, and then select Project. The New Project dialog box appears.

  2. In the Project Types pane, select the Visual C++ node, and then in the Templates pane, select Win32 Project.

  3. In the Name box, enter PGODemo.

  4. Click the OK button. The Win32 Application Wizard appears.

  5. Keep all default settings. Click the Finish button.

    Now you have a solution and a project named PGODemo. Next, create a DLL project.

  6. In the Solution Explorer, right-click on the solution, and select Add. And then click New Project. The New Project dialog box appears.

  7. In the Project Types pane, select the Visual C++ node, and then in the Templates pane, select Win32 Project.

  8. In the Name box, enter PGODemoDLL.

  9. Click the OK button. The Win32 Application Wizard appears.

  10. In the Application Settings page, choose DLL Application type and click Finish.

    You will now have a DLL project named PGODemoDLL.

  11. On the Solution Explorer, double click on PGODemoDLL project, double click on PGODemoDLL.cpp and add the following code:

    __declspec(dllexport) void HelloMessage(void)
    {
       MessageBox(NULL, L"hello", L"PGODemoDLL", MB_OK);
    }
    
  12. On the Solution Explorer, double click on PGODemo project, double click on PGODemo.cpp and add the following declaration before the definition of the function _tWinMain:

    __declspec(dllimport) void HelloMessage(void);
    
  13. In _tWinMain before the main message loop add the following code:

    HelloMessage();
    
  14. In the Solution Explorer, right click on the PDODemo solution and click Project Dependencies. The Project Dependencies dialog will appear.

  15. In the Dependencies page click chose PGODemo in the Projects combo box. Check the PGODemoDLL in the Depends on list.

    Next, you will create the PGIRelease and PGORelease configurations.

  16. In the Solution Explorer, right click on the solution, click Configuration Manager. Click on the Configuration combo box for PGODemo project and click <New …>. The New Project Configuration dialog box will appear.

    In the Project Configuration Name edit box type PGIRelease and choose Release in the Copy settings from combo box. Make sure the Create new solution configuration check box is checked.

    Repeat the same step on the PGODemoDLL project and to add the PGIRelease configuration to this project. Make sure that Create new solution configuration check box is not checked this time.

  17. Repeat step 16 for both projects to create PGORelease configuration. Make sure it also copies the settings from the Release configuration. Close the Configuration Manager dialog box.

    Now we have created two configurations, PGIRelease and PGORelease.

  18. In the Solution Explorer, right click on the PGODemo Project and click Properties. In the Configuration combo box choose the PGIRelease configuration. In Configuration Properties click General. Click the Whole Program Optimization combo box and choose the Profile Guided Optimization – Instrument option. Click Apply to save your changes.

  19. In the Configuration combo box choose the PGORelease configuration. In Configuration Properties click General. Click the Whole Program Optimization combo box and choose the Profile Guided Optimization - Optimize. Click Apply to save your changes.

  20. Repeat steps 18 and 19 on the PGIRelease and PGORelease configurations for the PGODemoDLL project.

    Now we will change the Intermediate Directory for the PGORelease configuration to be the same as the Output directory for the PGIRelease configuration for both projects.

  21. In the Solution Explorer, right-click on the PGODemo Project and click Properties. In the Configuration combo box choose the PGORelease configuration. In Configuration properties click General. In the Intermediate Directory, type $(SolutionDir)PGIRelease. Click Apply and close the dialog.

  22. Repeat step 21 for the PGODemoDLL project.

    Next, we will add the path of PGODemoDLL.dll to the path environment variable of the PGODemo application.

  23. In the Solution Explorer, right click on the PGODemo Project and click Properties. In the Configuration combo box choose the PGIRelease configuration. In Configuration Properties click Debugging. In the Environment, type the following and then click Apply:

    path=%path%;$(SolutionDir)PGODemoDLL\PGIRelease

    In the Configuration combo box choose the PGORelease configuration. In Configuration properties click Debugging. In the Environment, type the following:

    path=%path%;$(SolutionDir)PGODemoDLL\PGORelease

    Then click Apply and then click OK to close the dialog.

  24. In the Solution Explorer, right click on the PGODemo Project and click Properties. In the Configuration combo box choose the PGORelease configuration. In Configuration Properties click Linker and then click Optimization. In the Profile Guided Database edit box, replace $(TargetDir) with $(IntDir)\.

    Repeat this step for PGODemoDLL project.

  25. In the Solution Explorer, right click on the PGODemoDLL Project and click Properties. In the Configuration combo box choose the PGORelease configuration. In Configuration Properties click Linker and then click Advanced. In the Import Library edit box, replace $(TargetDir) with $(IntDir)\.

  26. In the standard toolbar click the Solution Configurations combo and choose the PGIRelease configuration. In the Solution Explorer, right click on the solution and click Build Solution.

    This will build the instrumented bits for both projects.

  27. Click the Debug menu and click Start Debugging or Start without Debugging. This will start PGODemo. After you shutdown the application, two .PGC files will be created, one on each of the two output folders PGODemo\PGIRelease and PGODemoDLL\PGIRelease.

  28. In the standard toolbar click the Solution Configurations combo and choose the PGORelease configuration. In the Solution Explorer, right click on the solution and click Build Solution.

    Now you have the PGO optimized images in the PGORelease configuration folders for both projects

Custom Profile Data Collection

The default behavior for profile data collection is to save all the data that describe the behavior of the instrumented application since its startup until it shuts down. PGO comes with a tool called PGOSWEEP that helps you customizing the profile data collection. You can use PGOSWEEP to collect profile data for some specific time frame during the profile scenario run.

In the following steps you will learn how to use the Visual Studio development environment and the command line tools to control the profile data collection.

To create a Win32 project

  1. On the File menu, select New, and then select Project. The New Project dialog box appears.

  2. In the Project Types pane, select the Visual C++ Projects node, and then in the Templates pane, select Win32 Project.

  3. In the Name box, enter PGODemo.

  4. Click the OK button. The Win32 Application Wizard appears.

  5. Keep all default settings. Click the Finish button.

To build instrumented PGODemo project in the IDE

  1. In the standard toolbar, click the Solution Configuration combo box and choose the Release configuration.

  2. In the Solution Explorer, right click on the PGODemo project. Click Profile Guided Optimization from the shortcut menu, and then click Instrument.

  3. In the Solution Explorer, right click on the PGODemo project. Click Profile Guided Optimization from the shortcut menu, and then click Run Instrumented/Optimized Application. This will launch your application. Note that you can also launch the instrumented application using the Start Debugging or Start Without Debugging from the Debug menu as normal.

  4. Click the Tools menu, click External Tools. The External Tools dialog appears. Click Add. In the Title edit box, type Pgosweep. Click the Browse button next to the Command edit box and locate the path to the PGOSWEEP tool. PGOSWEEP should be installed in the …\VC\bin folder where Visual Studio is installed. Check the Prompt for arguments check box and then click OK to close the External Tools dialog.

  5. From the Tools menu click Pgosweep. A dialog box appears. In the Arguments edit box, type:

    $(TargetPath) $(TargetDir)$(TargetName)_custom!1.pgc
    

    and click OK.

  6. In the PGODemo main window click File and click Exit to end the profile data collection run.

  7. Now, if you look at the $(OutDir), you will find two .PGC files. PGODemo_custom!1.pgc is the one that was created by PGOSWEEP and has the profile data from the beginning of the profile run until the time we called PGOSWEEP. The second one will have the default naming scheme PGODemo!1.pgc and contains profile data from the point after the sweeping until the we shut down the instrumented application.

  8. It’s very important to note that only the .PGC files that obey the standard naming $(ProjectName)!n.PGC where n is a number, will be merged automatically when you build the Optimized image. To merge PGODemo_custom!1.pgc, we created in the previous step, you will have to add a custom merge step (Please see the Custom Profile Data Merge scenario described earlier in this walkthrough).

Using these steps, you can control profile data collection and--in turn--optimize your application based on the most important parts of the application at run time.

Collecting Profile Data from the Command Line

You can use the command line tools to perform custom profile data collection as follows.

To build merged profile dated from the command line

  1. Create the instrumented executable:

    cl.exe /c /GL /O2 S1.cpp Sn.cpp 
    link /ltcg:pgi S1.obj Sn.obj /out:myapp.exe 
    
  2. Run the instrumented myapp.exe and, at the desired point while it’s running, use the pgosweep tool to collect the profile data:

    Pgosweep myapp.exe mycustomdata.pgc
    

Note PGC files that do not obey the standard format will have to be merged manually using the Pgomgr tool.

  1. After myapp.exe shuts down, another .PGC file (myapp!1.pgc) will be created automatically. Make sure to delete this one or move it outside the linker working directory before you run the linker to build the optimized myapp.exe, if you do not want it to be used as a part of the profile data.

  2. Merge mycustomdata.pgc using Pgomgr:

    Pgomgr –merge mycustomdata.pgc myapp.pgd
    
  3. Run the link command to create the final optimized application:

    link /ltcg:pgo /pgd:myapp
    

Custom profile data collection with PgoAutoSweep

You can call PgoAutoSweep from your application to save and reset the profile data at any point at runtime. The example below shows how this works

The example below will create two .PGC files. The first contains data that describes the runtime behavior until count is equal to 3, and the second contains the data collected after this point until application termination.

#include <stdio.h>
#include <windows.h>
#include <pgobootrun.h>

int count = 10;
int g = 0;

void func2(void)
{
    printf("hello from func2 %d\n", count);
    Sleep(2000);
}

void func1(void)
{
    printf("hello from func1 %d\n", count);
    Sleep(2000);
}
void main(void) 
{
    while (count--)
    {
        if(g)
            func2();
        else
            func1();
        if (count == 3) 
        {
            PgoAutoSweep("func1");
            g = 1;
        }
    }
    PgoAutoSweep("func2");
}

See Also

Other Resources

Walkthroughs in Visual C++ 2010