> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Profile-guided optimization in Visual Studio

> Profile-guided optimization in Visual Studio

This topic describes how to use [profile-guided optimizations](https://learn.microsoft.com/cpp/build/profile-guided-optimizations) (PGO) for games deployed and running on an XBOX Series X Dev Kit or XBOX One Dev Kit. PGO is a runtime compiler-optimization technology that uses profiling data collected while running important or performance-centric user scenarios to build an optimized version of the title.

Profile-guided optimizations have significant advantages over traditional static optimizations because they're based on how the title is likely to be used in a retail environment. PGO favors speed for code paths corresponding to common user scenarios and favors size for uncommon user scenarios. The result is faster code for common scenarios and smaller code for less frequently used scenarios.

Performance gains from PGO vary by title, but you can expect gains of 5-30 percent. Be aware that PGO doesn't address the performance of any GPU-centric parts of the application.

## Creating an instrumented build

Training with PGO relies on a build of your title that contains the PGO instrumentation. PGO uses this instrumentation to determine which code paths are executed most frequently. All you need to do to create an instrumented build is to set two build properties in Visual Studio.

#### To create an instrumented build

1. In **Solution Explorer**, right-click your project, and then select **Properties**.
2. In the **Property Pages** dialog box, expand the **Configuration Properties** and **C/C++** nodes.
3. Select the **Optimization** property page, and then set **Whole Program Optimization** to **Yes** (figure 1). **Figure 1.   Setting the Whole Program Optimization property.** <img src="https://mintcdn.com/microsoft-4404708b/stYRJgFi22xot4tO/images/gdk/tools/pgo_wpo.png?fit=max&auto=format&n=stYRJgFi22xot4tO&q=85&s=6ecb0d86d212e2b6aa8c5c95d0cf4d40" alt="Screenshot that shows the location of the Whole Program Optimization property" width="787" height="545" data-path="images/gdk/tools/pgo_wpo.png" />
4. Expand the **Linker** node.
5. Select the **Optimization** property page, and then set **Link Time Code Generation** to **Profile Guided Optimization - Instrument** (figure 2). **Figure 2.   Setting the Link Time Code Generation property for an instrumented build.** <img src="https://mintcdn.com/microsoft-4404708b/stYRJgFi22xot4tO/images/gdk/tools/pgo_instrumented_build.png?fit=max&auto=format&n=stYRJgFi22xot4tO&q=85&s=03a70b82d39722d95fc1ccfef8ceb5cd" alt="Screenshot that shows the location of the Link Time Code Generation property, set to create an instrumented build" width="787" height="546" data-path="images/gdk/tools/pgo_instrumented_build.png" /> \[!NOTE] The two properties described in this procedure correspond to the `/GL` compiler switch and the `/LTCG:PGInstrument` linker switch in MSBuild.
6. Build and deploy the instrumented build to your XBOX One console. With your title running, you can see that the PGO files are deployed as part of your title, similar to figure 3. **Figure 3.   The PGO files deployed by an instrumented build.** <img src="https://mintcdn.com/microsoft-4404708b/z-rLYkO3Ax6HPtgm/images/gdk/tools/pgo_deployed_files.png?fit=max&auto=format&n=z-rLYkO3Ax6HPtgm&q=85&s=30778992c2fee2f3762bac43a8269b48" alt="Screenshot of CLI directory that shows the deployed PGO files" width="554" height="462" data-path="images/gdk/tools/pgo_deployed_files.png" />

## Deploying required files

The Microsoft Game Development Kit (GDK) includes three files that must be deployed with your title to use PGO. One file, named *psapi.dll*, is installed to *C:\Program Files (x86)\Microsoft GDK\edition\GXDK\bin*.  The other two, named *pgort140.dll* and *pgosweep.exe*, come from your Visual Studio installation.

If you're using MSBuild to build your title, these files are automatically copied into your *Layout* directory when you create an instrumented build.

If you're using `makefiles` to build your title, you need to manually add these three files to your *Layout* directory so that they get deployed with your title. In Visual Studio, adding these files to your project and excluding them from the build is a convenient way to get the files copied to your *Layout* directory and deployed with the title.

#### To add the required files to your Visual Studio project

1. In **Solution Explorer**, right-click your project, select **Add**, and then select **Existing Item** (figure 4). **Figure 4.   Adding the PGO files to a project.** <img src="https://mintcdn.com/microsoft-4404708b/z-rLYkO3Ax6HPtgm/images/gdk/tools/pgo_add_binaries.png?fit=max&auto=format&n=z-rLYkO3Ax6HPtgm&q=85&s=7f212c1d64c1eb1ca76e4ed731fb1ef8" alt="Screenshot that shows how to add a file to a project" width="669" height="532" data-path="images/gdk/tools/pgo_add_binaries.png" />
2. Go to *C:\Program Files (x86)\Microsoft GDK\edition\GXDK\bin*, select the PGO file (*psapi.dll*), and then select **Add** to add the file to your project.
3. Go to the *C:\Program Files (x86)\Microsoft Visual Studio\2019\edition\VC\Tools\MSVC\version\bin\Hostx64\x64\onecore* -or- *C:\Program Files\Microsoft Visual Studio\2022\edition\VC\Tools\MSVC\version\bin\Hostx64\x64\onecore* for your toolset and select the PGO files (*pgort140.dll* and *pgosweep.exe*). Then select **Add** to add the files to your project.
4. In **Solution Explorer**, right-click *pgort140.dll*, and then select **Properties**.
5. In the **Property Pages** dialog box, expand the **Configuration Properties** node , and then select the **General** property page.
6. Set **Excluded From Build** to **Yes**, and then set **Item Type** to **Does not participate in build** (figure 5). **Figure 5.   Excluding a PGO file from builds.** <img src="https://mintcdn.com/microsoft-4404708b/z-rLYkO3Ax6HPtgm/images/gdk/tools/pgo_exclude_binaries.png?fit=max&auto=format&n=z-rLYkO3Ax6HPtgm&q=85&s=3ad61a9625ce53e6776c58e0f8f990d5" alt="Screenshot that shows how to exclude a PGO file from builds" width="788" height="640" data-path="images/gdk/tools/pgo_exclude_binaries.png" />

The PGO files will now be copied to your *Layout* directory and deployed with your title.

## Training with the instrumented build

Training is the most important phase of PGO. The performance gains you attain with PGO are a direct function of how well the application is trained. For the training phase of PGO, exercise common performance-centric scenarios with your title running.

After you exercise the common performance scenarios, initiate collection of a PGO artifact (.pgc) file, which captures your training data. Use *pgosweep.exe* to generate your .pgc file (figure 6).

**Figure 6.   Running pgosweep.exe.**

<img src="https://mintcdn.com/microsoft-4404708b/stYRJgFi22xot4tO/images/gdk/tools/pgo_run_pgosweep.png?fit=max&auto=format&n=stYRJgFi22xot4tO&q=85&s=19e5af6dae653bff3e8ff35815c156bf" alt="Screenshot that shows pgosweep.exe being run by using the command &#x22;xbrun /x/title /O g:\pgosweep.exe Direct3DGame1.exe d:\Direct3DGame1!1.pgc&#x22;" width="740" height="68" data-path="images/gdk/tools/pgo_run_pgosweep.png" />

In this example, we created a .pgc file named *Direct3DGame1!1.pgc*. When creating a .pgc file, we typically use the convention *titlename!#.pgc*, where *titlename* is the name of the running title and *#* is 1 plus the number of *titlename!#.pgc* files you created previously.

Each run of *pgosweep.exe* creates a separate .pgc file. Ideally, you'll create numerous .pgc files representing various performance-centric scenarios. When you finish creating your .pgc files, you can see them in the *D:\\* directory of your **console** (i.e. SystemScratch), similar to figure 7.

**Figure 7.   Sequentially named .pgc files.**

<img src="https://mintcdn.com/microsoft-4404708b/stYRJgFi22xot4tO/images/gdk/tools/pgo_pgc_files.png?fit=max&auto=format&n=stYRJgFi22xot4tO&q=85&s=9fb63ae09835246453011a1e670267e3" alt="Screenshot that shows a directory listing of three sequentially named .pgc files" width="509" height="204" data-path="images/gdk/tools/pgo_pgc_files.png" />

Next, you need to merge your .pgc files into another PGO artifact known as the .pgd file. The .pgd file is used by the compiler during the last phase of PGO, the optimization.

Before starting the optimization, copy your .pgc files from your console back to your PC by using [xbcp.exe](/tools/tools-console/commandlinetools/xbcp). The .pgc files must be copied to your build output directory. (In figure 8, the build output directory is *C:\temp\Direct3DGame1\Gaming.Xbox.XboxOne.x64\Release*.)

**Figure 8.   Copying .pgc files to the build output directory.**

<img src="https://mintcdn.com/microsoft-4404708b/stYRJgFi22xot4tO/images/gdk/tools/pgo_pgc_file_copy.png?fit=max&auto=format&n=stYRJgFi22xot4tO&q=85&s=2968da3f83e400958c52e50eb65f5ac4" alt="Screenshot that shows .pgc files being copied from the console to a build output directory" width="651" height="129" data-path="images/gdk/tools/pgo_pgc_file_copy.png" />

## Creating the optimized build

To create your optimized build, set the **Link Time Code Generation** property to **Profile Guided Optimization - Update** (figure 9).

**Figure 9.   Setting the Link Time Code Generation property for an optimized build.**

<img src="https://mintcdn.com/microsoft-4404708b/stYRJgFi22xot4tO/images/gdk/tools/pgo_optimized_build.png?fit=max&auto=format&n=stYRJgFi22xot4tO&q=85&s=8b2cca5395984b3e25478674c66d0a6e" alt="Screenshot that shows the location of the Link Time Code Generation property, set to create an optimized build" width="787" height="543" data-path="images/gdk/tools/pgo_optimized_build.png" />

<Note>
  This property corresponds to the `/LTCG:PGOptimize` linker switch in MSBuild.
</Note>

After you rebuild your title, your build output includes PGO-related messages, similar to those in figure 10.

**Figure 10.   PGO-related messages in build output.**

<img src="https://mintcdn.com/microsoft-4404708b/stYRJgFi22xot4tO/images/gdk/tools/pgo_optimized_build_output.png?fit=max&auto=format&n=stYRJgFi22xot4tO&q=85&s=67ad41198da6a7925eeca4761b438038" alt="Screenshot that shows an excerpt of build output that includes PGO-related messages" width="731" height="263" data-path="images/gdk/tools/pgo_optimized_build_output.png" />

## Recommendations for PGO for XBOX

The preceding instructions provide an overview for using PGO on the Microsoft Game Development Kit (GDK) on XBOX by using the built-in Visual Studio project properties. The Visual C++ compiler, however, has deprecated use of PGO via the `/LTCG:PGInstrument`, `/LTCG:PGOptimize`, and `/LTCG:PGUpdate` switches, which the Visual Studio project properties control in Visual Studio 2019 and Visual Studio 2022.

The preferred replacements are as follows.

* For the C/C++ compiler, use `/GL` (**Whole Program Optimization** property set to **Yes (/GL)**, as shown earlier in figure 1).
* For the linker, use `/LTCG` (**Link Time Code Generation** property set to **Use Link Time Code Generation (/LTCG)**, as shown in figure 11). **Figure 11.   Setting the Link Time Code Generation property.** <img src="https://mintcdn.com/microsoft-4404708b/stYRJgFi22xot4tO/images/gdk/tools/pgo_ltcg_new_linker_switch1.png?fit=max&auto=format&n=stYRJgFi22xot4tO&q=85&s=d5400ad2c7d5451776e58d3454a56095" alt="Screenshot that shows the location of the Link Time Code Generation property" width="601" height="415" data-path="images/gdk/tools/pgo_ltcg_new_linker_switch1.png" />

Then use one of the following new linker switches by adding it to the **Additional Options** box on the **Command Line** property page:

* `/FASTGENPROFILE` or `/GENPROFILE` to generate a PGO profile (figure 12). For details about these switches, see [ /GENPROFILE, /FASTGENPROFILE (Generate Profiling Instrumented Build)](https://learn.microsoft.com/cpp/build/reference/genprofile-fastgenprofile-generate-profiling-instrumented-build) on Microsoft Docs. **Figure 12.   Setting the linker switch to generate a PGO profile.** <img src="https://mintcdn.com/microsoft-4404708b/stYRJgFi22xot4tO/images/gdk/tools/pgo_ltcg_new_linker_switch2.png?fit=max&auto=format&n=stYRJgFi22xot4tO&q=85&s=6d24306b34e2a2282af826c5d05e9075" alt="Screenshot that shows the /FASTGENPROFILE linker switch added to the Command Line property page" width="601" height="415" data-path="images/gdk/tools/pgo_ltcg_new_linker_switch2.png" />
* `/USEPROFILE` to optimize for a set of PGO profiles (figure 13). For details about this switch, see [/USEPROFILE (Run PGO in thread safe mode)](https://learn.microsoft.com/cpp/build/reference/useprofile) on Microsoft Docs. **Figure 13.   Setting the linker switch to optimize for a set of PGO profiles.** <img src="https://mintcdn.com/microsoft-4404708b/stYRJgFi22xot4tO/images/gdk/tools/pgo_ltcg_new_linker_switch3.png?fit=max&auto=format&n=stYRJgFi22xot4tO&q=85&s=6eb5e198e65bf9ced6af8c947c5702a0" alt="Screenshot that shows the /USEPROFILE linker switch added to the Command Line property page" width="601" height="415" data-path="images/gdk/tools/pgo_ltcg_new_linker_switch3.png" />

## Troubleshooting PGO

### Runtime performance

When profiling an instrumented build, the tooling can cause performance issues. Such issues might make your title difficult to control. The `/FASTGENPROFILE` switch is a good choice for making an instrumented build faster for profiling interactive game sessions.

### Dependencies

If you enable PGO instrumentation and then discover that your title no longer loads, verify that *pgort140.dll* and *vcruntime140.dll* are in the same folder as your title .exe file.

If attempting to run *pgosweep.exe* fails (usually with a STATUS\_DLL\_NOT\_FOUND error), verify that *pgort140.dll*, *psapi.dll*, and *vcruntime140.dll* are present in the same folder as your title .exe file.

Also be sure you are using the x64 *onecore* version of *pgort140.dll* and *pgosweep.exe*.

### Memory usage

PGO uses memory to capture the profile, which can be a challenge for a title that uses a significant portion of available memory. To perform PGO successfully, you might need to use the ExtraTitleMemory setting in [xbconfig.exe](/tools/tools-console/commandlinetools/xbconfig), the [XMemTransferMemory](/reference/system/xmem/functions/xmemtransfermemory) function, or both.

Using `/FASTGENPROFILE` rather than `/LTCG:PGInstrument` or `/GENPROFILE` produces a smaller memory footprint with a similar result.

\[!NOTE] The version of PGO that ships in the June 2020 GDK (and its QFEs) uses title memory. PGO will be updated to properly use tooling memory in a future release.

## See also

[Profile-guided optimization](/tools/tools-console/pgo/pgo) [XBOX console game development (environment and tools)](/tools/tools-console/gc-tools-console-toc)


## Related topics

- [Profile-guided optimization](/tools/tools-console/pgo/pgo.md)
- [Profile-Guided Optimization (PGO) for XBOX titles](/tools/tools-console/pgo/index.md)
- [XBOX console game development environment and tools](/tools/tools-console/gc-tools-console-toc.md)
- [XBOX environment tools and APIs](/tools/tools-console/gc-xbox-tools-and-apis-toc.md)
- [XBOX Partner Onboarding for access and publishing](/home/onboarding.md)
