Anyone have success with profile-guided optimization in MSVC?

hey all, hope you’re well.

i discovered that two very similar windows environments (same msvc, same code, one win10 AMD machine and one win11 intel NUC) were building slightly different code: the win10 machine generates code that’s reliably about 5% faster (!!).

i tried diffing everything and i’m out of ideas, my code and build scripts are pretty clean and the environments seem basically identical.

i’m guessing some optimization heuristic is firing differently based on … something. so i thought i’d try using PGO to give consistent optimization hints to the linker.

however, i’m having trouble making it work:

this is what works:

  • i can get my VST3 generating filename!n.pgc files when i run my (“Release” compiled) program hosted in reaper.
  • i can get my JUCE standalone app generating PGC and PGD files correctly

this is what doesn’t work:

  • .pgd files don’t get auto-generated for my vst3. i CAN force them to generate with pgosweep, but all the tools including msvc and pgomgr are complaining about the output file with “Unhandled PDB error”. there are no meaningful hits for this on google that seem relevant.
  • there doesn’t seem to be a way to swap the standalone app traces in for the vst3, the tools complain (even those the only instrumented module is the code common to both).
  • because of the above, linking VST3 with the profile file doesn’t work.
  • (i haven’t even started to worry about AAX builds)

…also some general unease about the weird workflow. do i have to re-run the manual profiling process with every release, or are the PGD files tolerant of program changes?

or should i just give up on the 5% perf difference? it’s like 0.1% CPU on this machine, but i’d like to make everything hermetic and reproducible.

(also asking gemini AI for help caused it to error out with “An error has occurred”, lol)

thanks!

(EDIT: ARGH I think I missed the /USEPROFILE flag. testing now…)

Hmm. Pretty sure I’m holding something wrong.

Ok, so I at least got a pipeline to complete with something like this (apologies for future readers if I missed anything):

Generate step:

  • VST3 project: Manually specify PGD location with the pgd linker args, add Linker flag: /GENPROFILE:EXACT
  • Change debug binary for Release VST3 to reaper.exe (or whatever host)
  • Build. Run debug pass, load a project with the plugin you’re profiling. You should get a PGD file generated. You might need to use pgomgr to merge future PGC files in for some reason. Also, ignore the PGC files created by the VST3 manifest helper.

So, now I have a PGD file, and pgomgr /summary shows appropriate information.

Optimize step:

  • Remove the /GENPROFILE flag from the linker
  • Build.

Ok, I don’t think this part worked properly, I’m not seeing any performance improvement in my program, and if I remove the PGD file nothing breaks so I’m not sure if I’m doing the optimize bit right.

Also i seem to have broken whatever magic was happening on this win10 machine and now it consistently makes software that runs at the (slower) speed of the win11 builds. I kept a copy of my old build folder so tomorrow’s first job is to see if i can figure out what changed…

If anyone else has a reliable recipe to make this work, guidance is appreciated. Thanks!

Success! Ok, so in the optimize step you also need to have the /USEPROFILE flag set in the linker.

With that change and whatever busted profile I managed to capture, I see about a 6-7% performance improvement now. Pretty substantial.

Edit: confirmed with a second plugin in a test suite. Project with 40 instances:

  • PRE: 7.6% total CPU
  • POST PGO: 7.3% total CPU (about 4% improvement)