In general, generating an optimized executable includes the following steps:
Build an instrumented app:
native-image --pgo-instrument MyApp
Run the instrumented executable and apply workloads to it to generate a profile file:
./myapp
This will generate a default.iprof file in the working directory. The quality of the workload (executing all relevant code paths) and giving the application enough time to collect profiles are essential for having complete profiling information and therefore the best performance. Note that the profile file won’t appear until after the application shutdown.
Build an optimized executable. The profiles file with default name and location will be picked up automatically, alternatively you can pass it along:
native-image --pgo=default.iprof MyApp
Now for a Quarkus application and building from Maven, what you can do is create corresponding profiles for those steps, for example:
<profile>
<id>instrumented</id>
…
<properties>
…
<quarkus.native.additional-build-args>--pgo-instrument</quarkus.native.additional-build-args>
</properties>
</profile>
and
<profile>
<id>optimized</id>
…
<properties>
…
<quarkus.native.additional-build-args>--pgo=${project.basedir}/default.iprof</quarkus.native.additional-build-args>
</properties>
</profile>
Alternatively the same should work from command line, for example:
./mvnw package -Dnative -Dquarkus.native.additional-build-args=--pgo=default.iprof