Skip to content

Commit f0b9531

Browse files
authored
Add PGO support to xcaddy (#259)
* Add PGO support * Add "Experimental" comments to code * Fix formatting
1 parent 14e0e39 commit f0b9531

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ $ xcaddy build [<caddy_version>]
6464
[--with <module[@version][=replacement]>...]
6565
[--replace <module[@version]=replacement>...]
6666
[--embed <[alias]:path/to/dir>...]
67+
[--pgo <file>] # EXPERIMENTAL
6768
```
6869

6970
- `<caddy_version>` is the core Caddy version to build; defaults to `CADDY_VERSION` env variable or latest.<br>
@@ -80,6 +81,8 @@ $ xcaddy build [<caddy_version>]
8081

8182
- `--embed` can be used to embed the contents of a directory into the Caddy executable. `--embed` can be passed multiple times with separate source directories. The source directory can be prefixed with a custom alias and a colon `:` to write the embedded files into an aliased subdirectory, which is useful when combined with the `root` directive and sub-directive.
8283

84+
- `--pgo` can be used to specify a file containing a profile to use for profile guided optimization. If a file named `default.pgo` is present in the current directory, it will automatically be used. This feature is new to xcaddy and is considered experimental.
85+
8386
#### Examples
8487

8588
```bash

builder.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type Builder struct {
4747
Debug bool `json:"debug,omitempty"`
4848
BuildFlags string `json:"build_flags,omitempty"`
4949
ModFlags string `json:"mod_flags,omitempty"`
50+
PgoProfile string `json:"pgo_profile,omitempty"` // Experimental
5051

5152
// Experimental: subject to change
5253
EmbedDirs []struct {
@@ -76,6 +77,12 @@ func (b Builder) Build(ctx context.Context, outputFile string) error {
7677
}
7778
log.Printf("[INFO] absolute output file path: %s", absOutputFile)
7879

80+
// likewise with the PGO profile
81+
absPgoProfile, err := filepath.Abs(b.PgoProfile)
82+
if err != nil {
83+
return err
84+
}
85+
7986
// set some defaults from the environment, if applicable
8087
if b.OS == "" {
8188
b.OS = utils.GetGOOS()
@@ -153,6 +160,10 @@ func (b Builder) Build(ctx context.Context, outputFile string) error {
153160
cmd, err := buildEnv.newGoBuildCommand(ctx, "build",
154161
"-o", absOutputFile,
155162
)
163+
if b.PgoProfile != "" {
164+
log.Printf("[INFO] using PGO profile %s", b.PgoProfile)
165+
cmd.Args = append(cmd.Args, "-pgo="+absPgoProfile)
166+
}
156167
if err != nil {
157168
return err
158169
}

cmd/commands.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ func init() {
1919
buildCommand.Flags().String("output", "", "change the output file name")
2020
buildCommand.Flags().StringArray("replace", []string{}, "like --with but for Go modules")
2121
buildCommand.Flags().StringArray("embed", []string{}, "embeds directories into the built Caddy executable to use with the `embedded` file-system")
22+
buildCommand.Flags().String("pgo", "", "file containing profile for PGO (experimental)")
2223
}
2324

2425
var versionCommand = &cobra.Command{
@@ -35,7 +36,8 @@ var buildCommand = &cobra.Command{
3536
[--output <file>]
3637
[--with <module[@version][=replacement]>...]
3738
[--replace <module[@version]=replacement>...]
38-
[--embed <[alias]:path/to/dir>...]`,
39+
[--embed <[alias]:path/to/dir>...]
40+
[--pgo <file>] # EXPERIMENTAL`,
3941
Long: `
4042
<caddy_version> is the core Caddy version to build; defaults to CADDY_VERSION env variable or latest.
4143
This can be the keyword latest, which will use the latest stable tag, or any git ref such as:
@@ -52,6 +54,8 @@ Flags:
5254
--replace is like --with, but does not add a blank import to the code; it only writes a replace directive to go.mod, which is useful when developing on Caddy's dependencies (ones that are not Caddy modules). Try this if you got an error when using --with, like cannot find module providing package.
5355
5456
--embed can be used to embed the contents of a directory into the Caddy executable. --embed can be passed multiple times with separate source directories. The source directory can be prefixed with a custom alias and a colon : to write the embedded files into an aliased subdirectory, which is useful when combined with the root directive and sub-directive.
57+
58+
--pgo is used to specify a specify a file containing a profile for profile-guided optimization (experimental)
5559
`,
5660
Short: "Compile custom caddy binaries",
5761
Args: cobra.MaximumNArgs(1),
@@ -60,6 +64,7 @@ Flags:
6064
var plugins []xcaddy.Dependency
6165
var replacements []xcaddy.Replace
6266
var embedDir []string
67+
var pgo string
6368
var argCaddyVersion string
6469
if len(args) > 0 {
6570
argCaddyVersion = args[0]
@@ -103,6 +108,19 @@ Flags:
103108
if err != nil {
104109
return fmt.Errorf("unable to parse --embed arguments: %s", err.Error())
105110
}
111+
112+
// Experimental: If no --pgo flag is specified and a default.pgo file is found, use that for PGO
113+
pgo, err = cmd.Flags().GetString("pgo")
114+
if err != nil {
115+
return fmt.Errorf("unable to parse --pgo arguments: %s", err.Error())
116+
}
117+
if pgo == "" {
118+
_, err = os.Stat("default.pgo")
119+
if err == nil {
120+
pgo = "default.pgo"
121+
}
122+
}
123+
106124
// prefer caddy version from command line argument over env var
107125
if argCaddyVersion != "" {
108126
caddyVersion = argCaddyVersion
@@ -127,6 +145,7 @@ Flags:
127145
Debug: buildDebugOutput,
128146
BuildFlags: buildFlags,
129147
ModFlags: modFlags,
148+
PgoProfile: pgo,
130149
}
131150
for _, md := range embedDir {
132151
if before, after, found := strings.Cut(md, ":"); found {

0 commit comments

Comments
 (0)