PGO is the thing that blew my mind the most about Go when i found out about it. It's classic Go a 'no way this exists' solution.
Go is compiled ahead of time. This means at build time, the Go source code is translated directly into machine code for a specific operating system and architecture, creating a self-contained executable file.
Unlike a JIT compiler, which performs compilation at runtime, allowing it to potentially make optimizations based on actual execution patterns.
JIT is the reason why JavaScript is decently faster than other dynamic languages like Python.
Because the JS engine runs a background process that inspect's the running machine code to identify hot-paths (repetitive sections that can be recompiled to produce more optimized machine code), same thing for the JVM.
While JIT produces faster code, it comes with a memory cost. Anyone who ran a production server for any of the JVM based languages or JavaScript knows the pain of scaling this at some point. So Go produces fast machine code at compile time with small memory footprint while JIT-compiled languages are faster during runtime.
But that's not actually it, Go has PGO. PGO allows the Go compiler to leverage real-world runtime information to make better optimization decisions during the ahead-of-time compilation process. Here's how it works:
1- Profiling: You run your compiled Go application in a realistic environment (testing or even production) and collect performance profiles. These profiles capture data about how the code executes like which functions are called most often (hot paths), how branches are typically taken, etc.
2- Recompilation: You then feed this profile data back into the Go compiler during the next build (go build -pgo=profile.pprof ...).
3- Optimized Build: The compiler uses the insights from the profile to make more informed decisions. It might inline functions more aggressively on hot paths, optimize code layout, or make other adjustments based on the observed runtime behavior.
The result is that Go can achieve the optimization benefits typically associated with JIT compilation but without the runtime overhead.
To enable PGO, first, you need to import the pprof package in your Go app like _ "net/http/pprof" which will automatically registers HTTP handlers like /debug/pprof/profile on Go's default HTTP server mux than runs with http.ListenAndServe().
Now fetch live profiles from the /debug/pprof/* endpoints using curl, than do the PGO build like the example below