agy-superpowers 5.2.1 → 5.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -150
- package/package.json +1 -1
- package/template/agent/patches/skills-patches.md +23 -0
- package/template/agent/rules/scratch-scripts.md +37 -0
- package/template/agent/rules/superpowers.md +6 -50
- package/template/agent/skills/brainstorming/SKILL.md +4 -3
- package/template/agent/skills/brainstorming/visual-companion.md +2 -3
- package/template/agent/skills/finishing-a-development-branch/SKILL.md +11 -16
- package/template/agent/skills/subagent-driven-development/SKILL.md +16 -0
- package/template/agent/skills/subagent-driven-development/implementer-prompt.md +4 -3
- package/template/agent/skills/using-git-worktrees/SKILL.md +3 -2
- package/template/agent/skills/using-superpowers/SKILL.md +8 -6
- package/template/agent/skills/using-superpowers/references/copilot-tools.md +52 -0
- package/template/agent/skills/writing-plans/SKILL.md +5 -3
- package/template/agent/skills/writing-skills/SKILL.md +1 -1
- package/template/agent/superpowers-version.json +2 -2
- package/template/agent/tmp/agent-config-backup.yml +9 -0
- package/template/agent/skills/ai-integrated-product/SKILL.md +0 -57
- package/template/agent/skills/analytics-setup/SKILL.md +0 -51
- package/template/agent/skills/api-design/SKILL.md +0 -193
- package/template/agent/skills/app-store-optimizer/SKILL.md +0 -127
- package/template/agent/skills/auth-and-identity/SKILL.md +0 -167
- package/template/agent/skills/backend-developer/SKILL.md +0 -148
- package/template/agent/skills/bootstrapper-finance/SKILL.md +0 -55
- package/template/agent/skills/chrome-extension-developer/SKILL.md +0 -53
- package/template/agent/skills/community-manager/SKILL.md +0 -115
- package/template/agent/skills/content-marketer/SKILL.md +0 -111
- package/template/agent/skills/conversion-optimizer/SKILL.md +0 -142
- package/template/agent/skills/cto-architect/SKILL.md +0 -133
- package/template/agent/skills/customer-success-manager/SKILL.md +0 -126
- package/template/agent/skills/data-analyst/SKILL.md +0 -147
- package/template/agent/skills/devops-engineer/SKILL.md +0 -117
- package/template/agent/skills/email-infrastructure/SKILL.md +0 -164
- package/template/agent/skills/game-design/SKILL.md +0 -194
- package/template/agent/skills/game-developer/SKILL.md +0 -175
- package/template/agent/skills/growth-hacker/SKILL.md +0 -122
- package/template/agent/skills/idea-validator/SKILL.md +0 -55
- package/template/agent/skills/indie-legal/SKILL.md +0 -53
- package/template/agent/skills/influencer-marketer/SKILL.md +0 -141
- package/template/agent/skills/landing-page-builder/SKILL.md +0 -59
- package/template/agent/skills/launch-strategist/SKILL.md +0 -62
- package/template/agent/skills/market-researcher/SKILL.md +0 -53
- package/template/agent/skills/micro-saas-builder/SKILL.md +0 -56
- package/template/agent/skills/monetization-strategist/SKILL.md +0 -119
- package/template/agent/skills/paid-acquisition-specialist/SKILL.md +0 -119
- package/template/agent/skills/pricing-psychologist/SKILL.md +0 -58
- package/template/agent/skills/real-time-features/SKILL.md +0 -194
- package/template/agent/skills/retention-specialist/SKILL.md +0 -123
- package/template/agent/skills/rust-developer/SKILL.md +0 -281
- package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +0 -231
- package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +0 -124
- package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +0 -132
- package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +0 -95
- package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +0 -141
- package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +0 -125
- package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +0 -127
- package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +0 -120
- package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +0 -156
- package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +0 -122
- package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +0 -167
- package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +0 -134
- package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +0 -143
- package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +0 -121
- package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +0 -143
- package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +0 -187
- package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +0 -165
- package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +0 -177
- package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +0 -163
- package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +0 -146
- package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +0 -160
- package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +0 -125
- package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +0 -162
- package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +0 -177
- package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +0 -184
- package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +0 -168
- package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +0 -182
- package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +0 -199
- package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +0 -175
- package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +0 -185
- package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +0 -203
- package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +0 -158
- package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +0 -195
- package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +0 -156
- package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +0 -191
- package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +0 -198
- package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +0 -167
- package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +0 -169
- package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +0 -172
- package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +0 -189
- package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +0 -113
- package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +0 -147
- package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +0 -122
- package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +0 -161
- package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +0 -149
- package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +0 -138
- package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +0 -169
- package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +0 -116
- package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +0 -128
- package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +0 -136
- package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +0 -179
- package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +0 -144
- package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +0 -152
- package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +0 -145
- package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +0 -133
- package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +0 -152
- package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +0 -124
- package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +0 -115
- package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +0 -151
- package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +0 -130
- package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +0 -155
- package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +0 -138
- package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +0 -107
- package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +0 -118
- package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +0 -157
- package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +0 -133
- package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +0 -136
- package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +0 -135
- package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +0 -122
- package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +0 -172
- package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +0 -168
- package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +0 -168
- package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +0 -147
- package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +0 -158
- package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +0 -139
- package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +0 -147
- package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +0 -149
- package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +0 -174
- package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +0 -159
- package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +0 -138
- package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +0 -156
- package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +0 -172
- package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +0 -164
- package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +0 -99
- package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +0 -104
- package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +0 -94
- package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +0 -78
- package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +0 -76
- package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +0 -123
- package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +0 -127
- package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +0 -129
- package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +0 -131
- package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +0 -86
- package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +0 -118
- package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +0 -92
- package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +0 -65
- package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +0 -101
- package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +0 -161
- package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +0 -187
- package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +0 -152
- package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +0 -141
- package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +0 -181
- package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +0 -160
- package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +0 -130
- package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +0 -167
- package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +0 -144
- package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +0 -141
- package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +0 -95
- package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +0 -135
- package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +0 -124
- package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +0 -135
- package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +0 -134
- package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +0 -134
- package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +0 -105
- package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +0 -65
- package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +0 -97
- package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +0 -122
- package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +0 -119
- package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +0 -153
- package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +0 -136
- package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +0 -133
- package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +0 -120
- package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +0 -137
- package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +0 -134
- package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +0 -150
- package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +0 -123
- package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +0 -113
- package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +0 -175
- package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +0 -149
- package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +0 -133
- package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +0 -148
- package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +0 -130
- package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +0 -120
- package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +0 -155
- package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +0 -139
- package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +0 -135
- package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +0 -162
- package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +0 -186
- package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +0 -162
- package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +0 -160
- package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +0 -151
- package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +0 -171
- package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +0 -168
- package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +0 -151
- package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +0 -144
- package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +0 -189
- package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +0 -226
- package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +0 -161
- package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +0 -130
- package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +0 -127
- package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +0 -154
- package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +0 -142
- package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +0 -146
- package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +0 -160
- package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +0 -159
- package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +0 -144
- package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +0 -137
- package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +0 -188
- package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +0 -143
- package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +0 -131
- package/template/agent/skills/saas-architect/SKILL.md +0 -139
- package/template/agent/skills/security-engineer/SKILL.md +0 -133
- package/template/agent/skills/seo-specialist/SKILL.md +0 -130
- package/template/agent/skills/solo-founder-ops/SKILL.md +0 -56
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
# opt-inline-small
|
|
2
|
-
|
|
3
|
-
> Use `#[inline]` for small hot functions
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Function call overhead (stack frame setup, register saves, jumps) can dominate small functions. Inlining eliminates this overhead and enables further optimizations by the compiler. The compiler often inlines automatically, but hints help for cross-crate calls.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// Small hot function without inline hint
|
|
13
|
-
// May not be inlined across crate boundaries
|
|
14
|
-
fn is_ascii_digit(b: u8) -> bool {
|
|
15
|
-
b >= b'0' && b <= b'9'
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Called millions of times
|
|
19
|
-
for byte in data {
|
|
20
|
-
if is_ascii_digit(*byte) { // Function call overhead
|
|
21
|
-
count += 1;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Good
|
|
27
|
-
|
|
28
|
-
```rust
|
|
29
|
-
#[inline]
|
|
30
|
-
fn is_ascii_digit(b: u8) -> bool {
|
|
31
|
-
b >= b'0' && b <= b'9'
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Now the compiler will inline this
|
|
35
|
-
for byte in data {
|
|
36
|
-
if is_ascii_digit(*byte) { // Inlined, no call overhead
|
|
37
|
-
count += 1;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Inline Attributes
|
|
43
|
-
|
|
44
|
-
```rust
|
|
45
|
-
// No attribute - compiler decides (usually good for same-crate)
|
|
46
|
-
fn auto_decide() { }
|
|
47
|
-
|
|
48
|
-
// Suggest inlining - helps cross-crate
|
|
49
|
-
#[inline]
|
|
50
|
-
fn suggest_inline() { }
|
|
51
|
-
|
|
52
|
-
// Strongly suggest inlining - almost always inlined
|
|
53
|
-
#[inline(always)]
|
|
54
|
-
fn force_inline() { }
|
|
55
|
-
|
|
56
|
-
// Strongly suggest NOT inlining - for large/cold code
|
|
57
|
-
#[inline(never)]
|
|
58
|
-
fn prevent_inline() { }
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## When to Use Each
|
|
62
|
-
|
|
63
|
-
```rust
|
|
64
|
-
// #[inline] - Small functions, especially in libraries
|
|
65
|
-
#[inline]
|
|
66
|
-
pub fn len(&self) -> usize {
|
|
67
|
-
self.inner.len()
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// #[inline(always)] - Critical hot path, verified by profiling
|
|
71
|
-
#[inline(always)]
|
|
72
|
-
fn hot_inner_loop_helper(x: u32) -> u32 {
|
|
73
|
-
x.wrapping_mul(0x9E3779B9)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// #[inline(never)] - Error handlers, cold paths
|
|
77
|
-
#[inline(never)]
|
|
78
|
-
fn handle_error(err: Error) -> ! {
|
|
79
|
-
eprintln!("Fatal: {}", err);
|
|
80
|
-
std::process::exit(1);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// No attribute - large functions, infrequent calls
|
|
84
|
-
fn complex_processing(data: &mut Data) {
|
|
85
|
-
// Many lines of code...
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
## Evidence from ripgrep
|
|
90
|
-
|
|
91
|
-
```rust
|
|
92
|
-
// https://github.com/BurntSushi/ripgrep/blob/master/crates/printer/src/standard.rs
|
|
93
|
-
|
|
94
|
-
#[inline(always)]
|
|
95
|
-
fn write_prelude(
|
|
96
|
-
&self,
|
|
97
|
-
absolute_byte_offset: u64,
|
|
98
|
-
line_number: Option<u64>,
|
|
99
|
-
column: Option<u64>,
|
|
100
|
-
) -> io::Result<()> {
|
|
101
|
-
// Hot path in printing matches
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
#[inline(always)]
|
|
105
|
-
fn write_line(&self, line: &[u8]) -> io::Result<()> {
|
|
106
|
-
// Called for every line
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## Generic Functions
|
|
111
|
-
|
|
112
|
-
```rust
|
|
113
|
-
// Generic functions are already candidates for per-monomorphization inlining
|
|
114
|
-
// But #[inline] helps ensure it across crates
|
|
115
|
-
|
|
116
|
-
#[inline]
|
|
117
|
-
pub fn min<T: Ord>(a: T, b: T) -> T {
|
|
118
|
-
if a < b { a } else { b }
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## Cautions
|
|
123
|
-
|
|
124
|
-
```rust
|
|
125
|
-
// DON'T inline large functions - hurts instruction cache
|
|
126
|
-
#[inline(always)] // BAD for large function
|
|
127
|
-
fn large_complex_function(data: &mut [u8]) {
|
|
128
|
-
// 100+ lines of code
|
|
129
|
-
// Inlining bloats every call site
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// DON'T assume inlining always helps - measure!
|
|
133
|
-
// Sometimes the compiler makes better decisions
|
|
134
|
-
|
|
135
|
-
// Inlining is non-transitive
|
|
136
|
-
#[inline]
|
|
137
|
-
fn outer() {
|
|
138
|
-
inner(); // inner() also needs #[inline] to be inlined together
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
fn inner() { } // Won't be inlined at outer's call sites
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
## Verifying Inlining
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
# Check if function was inlined using Cachegrind
|
|
148
|
-
# Non-inlined functions show entry/exit counts
|
|
149
|
-
|
|
150
|
-
# Or examine assembly
|
|
151
|
-
cargo rustc --release -- --emit=asm
|
|
152
|
-
# Look for call instructions vs inlined code
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
## See Also
|
|
156
|
-
|
|
157
|
-
- [opt-inline-always-rare](opt-inline-always-rare.md) - Use #[inline(always)] sparingly
|
|
158
|
-
- [opt-inline-never-cold](opt-inline-never-cold.md) - Use #[inline(never)] for cold paths
|
|
159
|
-
- [opt-cold-unlikely](opt-cold-unlikely.md) - Use #[cold] for unlikely paths
|
|
160
|
-
- [opt-lto-release](opt-lto-release.md) - LTO enables cross-crate inlining
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
# opt-likely-hint
|
|
2
|
-
|
|
3
|
-
> Use code structure to hint at likely branches; use intrinsics on nightly
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Modern CPUs predict branches to speculatively execute code. Mispredictions cause pipeline stalls (10-20 cycles). Helping the compiler understand which branches are likely allows it to generate optimal code layout and branch hints, improving performance in hot paths.
|
|
8
|
-
|
|
9
|
-
## Stable Rust: Code Structure Hints
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// Pattern 1: Early returns for unlikely cases
|
|
13
|
-
fn process(data: Option<&Data>) -> i32 {
|
|
14
|
-
// Compiler assumes early return is "unlikely"
|
|
15
|
-
let data = match data {
|
|
16
|
-
None => return 0, // Unlikely
|
|
17
|
-
Some(d) => d,
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
// Hot path continues here
|
|
21
|
-
complex_processing(data)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Pattern 2: if-else ordering
|
|
25
|
-
fn calculate(x: i32) -> i32 {
|
|
26
|
-
if x >= 0 {
|
|
27
|
-
// Put likely case in "if" branch
|
|
28
|
-
x * 2
|
|
29
|
-
} else {
|
|
30
|
-
// Unlikely case in "else"
|
|
31
|
-
handle_negative(x)
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Pattern 3: Cold function extraction
|
|
36
|
-
fn hot_path(data: &[u8]) -> Result<(), Error> {
|
|
37
|
-
if data.is_empty() {
|
|
38
|
-
return cold_empty_error(); // Extracted = unlikely
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
process_fast(data)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
#[cold]
|
|
45
|
-
fn cold_empty_error() -> Result<(), Error> {
|
|
46
|
-
Err(Error::EmptyInput)
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Nightly: Intrinsics
|
|
51
|
-
|
|
52
|
-
```rust
|
|
53
|
-
#![feature(core_intrinsics)]
|
|
54
|
-
use std::intrinsics::{likely, unlikely};
|
|
55
|
-
|
|
56
|
-
fn process(data: &Data) -> i32 {
|
|
57
|
-
if unlikely(data.is_corrupted()) {
|
|
58
|
-
return handle_corruption(data);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if likely(data.is_cached()) {
|
|
62
|
-
return fast_cached_path(data);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
slow_uncached_path(data)
|
|
66
|
-
}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## Boolean Likely Wrapper (Nightly)
|
|
70
|
-
|
|
71
|
-
```rust
|
|
72
|
-
#![feature(core_intrinsics)]
|
|
73
|
-
|
|
74
|
-
#[inline(always)]
|
|
75
|
-
fn likely(b: bool) -> bool {
|
|
76
|
-
std::intrinsics::likely(b)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
#[inline(always)]
|
|
80
|
-
fn unlikely(b: bool) -> bool {
|
|
81
|
-
std::intrinsics::unlikely(b)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Usage
|
|
85
|
-
if likely(x > 0) {
|
|
86
|
-
hot_path(x)
|
|
87
|
-
} else {
|
|
88
|
-
cold_path(x)
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## Stable: likely-stable Crate
|
|
93
|
-
|
|
94
|
-
```rust
|
|
95
|
-
use likely_stable::{likely, unlikely};
|
|
96
|
-
|
|
97
|
-
fn check(value: i32) -> bool {
|
|
98
|
-
if unlikely(value < 0) {
|
|
99
|
-
handle_negative()
|
|
100
|
-
} else if likely(value < 1000) {
|
|
101
|
-
handle_common()
|
|
102
|
-
} else {
|
|
103
|
-
handle_large()
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
## Loop Optimization
|
|
109
|
-
|
|
110
|
-
```rust
|
|
111
|
-
fn search(data: &[i32], target: i32) -> Option<usize> {
|
|
112
|
-
for (i, &item) in data.iter().enumerate() {
|
|
113
|
-
// Assume most iterations DON'T find the target
|
|
114
|
-
if unlikely(item == target) {
|
|
115
|
-
return Some(i);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
None
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Alternative: structure for likely case
|
|
122
|
-
fn search_common(data: &[i32], target: i32) -> Option<usize> {
|
|
123
|
-
// If target is usually found
|
|
124
|
-
for (i, &item) in data.iter().enumerate() {
|
|
125
|
-
if likely(item == target) {
|
|
126
|
-
return Some(i);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
None
|
|
130
|
-
}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
## Match Arm Ordering
|
|
134
|
-
|
|
135
|
-
```rust
|
|
136
|
-
// Put most common variants first
|
|
137
|
-
fn process_message(msg: Message) {
|
|
138
|
-
match msg {
|
|
139
|
-
// Most common - listed first
|
|
140
|
-
Message::Data(d) => handle_data(d),
|
|
141
|
-
Message::Heartbeat => (), // Second most common
|
|
142
|
-
|
|
143
|
-
// Rare cases last
|
|
144
|
-
Message::Error(e) => handle_error(e),
|
|
145
|
-
Message::Shutdown => shutdown(),
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
## Benchmark-Driven Hints
|
|
151
|
-
|
|
152
|
-
```rust
|
|
153
|
-
// Profile first to know which branches are actually likely!
|
|
154
|
-
fn speculative(x: i32) -> i32 {
|
|
155
|
-
// DON'T GUESS - measure with profiling
|
|
156
|
-
// perf record / perf report
|
|
157
|
-
// cargo flamegraph
|
|
158
|
-
|
|
159
|
-
if x > threshold { // Is this actually common?
|
|
160
|
-
path_a(x)
|
|
161
|
-
} else {
|
|
162
|
-
path_b(x)
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
## See Also
|
|
168
|
-
|
|
169
|
-
- [opt-cold-unlikely](./opt-cold-unlikely.md) - #[cold] for unlikely functions
|
|
170
|
-
- [opt-inline-never-cold](./opt-inline-never-cold.md) - Keeping cold code separate
|
|
171
|
-
- [perf-profile-first](./perf-profile-first.md) - Profile to know what's likely
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
# opt-lto-release
|
|
2
|
-
|
|
3
|
-
> Enable LTO in release builds
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Link-Time Optimization (LTO) enables optimizations across crate boundaries that aren't possible during normal compilation. This includes cross-crate inlining, dead code elimination, and devirtualization. Typically provides 5-20% performance improvement.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```toml
|
|
12
|
-
# Cargo.toml - default release profile
|
|
13
|
-
[profile.release]
|
|
14
|
-
opt-level = 3
|
|
15
|
-
# No LTO = missed optimization opportunities
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Good
|
|
19
|
-
|
|
20
|
-
```toml
|
|
21
|
-
# Cargo.toml - optimized release profile
|
|
22
|
-
[profile.release]
|
|
23
|
-
opt-level = 3
|
|
24
|
-
lto = "fat" # Maximum optimization
|
|
25
|
-
codegen-units = 1 # Better optimization (single codegen unit)
|
|
26
|
-
panic = "abort" # Smaller binary, no unwind tables
|
|
27
|
-
strip = true # Remove symbols for smaller binary
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## LTO Options Explained
|
|
31
|
-
|
|
32
|
-
```toml
|
|
33
|
-
# No LTO (default)
|
|
34
|
-
lto = false
|
|
35
|
-
|
|
36
|
-
# Thin LTO - fast compilation, most benefits
|
|
37
|
-
lto = "thin"
|
|
38
|
-
|
|
39
|
-
# Fat LTO - slowest compilation, maximum optimization
|
|
40
|
-
lto = "fat"
|
|
41
|
-
# Equivalent to:
|
|
42
|
-
lto = true
|
|
43
|
-
|
|
44
|
-
# Thin-local - LTO within each crate only
|
|
45
|
-
lto = "off"
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Trade-offs
|
|
49
|
-
|
|
50
|
-
| Setting | Compile Time | Binary Size | Performance |
|
|
51
|
-
|---------|--------------|-------------|-------------|
|
|
52
|
-
| `lto = false` | Fast | Larger | Baseline |
|
|
53
|
-
| `lto = "thin"` | Medium | Smaller | +5-15% |
|
|
54
|
-
| `lto = "fat"` | Slow | Smallest | +10-20% |
|
|
55
|
-
|
|
56
|
-
## Evidence from Production
|
|
57
|
-
|
|
58
|
-
```toml
|
|
59
|
-
# From Anchor (Solana framework)
|
|
60
|
-
# https://github.com/solana-foundation/anchor/blob/master/cli/src/rust_template.rs
|
|
61
|
-
[profile.release]
|
|
62
|
-
overflow-checks = true
|
|
63
|
-
lto = "fat"
|
|
64
|
-
codegen-units = 1
|
|
65
|
-
|
|
66
|
-
# From sol-trade-sdk
|
|
67
|
-
# https://github.com/0xfnzero/sol-trade-sdk
|
|
68
|
-
[profile.release]
|
|
69
|
-
opt-level = 3
|
|
70
|
-
lto = "fat"
|
|
71
|
-
codegen-units = 1
|
|
72
|
-
panic = "abort"
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## Complete Optimized Profile
|
|
76
|
-
|
|
77
|
-
```toml
|
|
78
|
-
[profile.release]
|
|
79
|
-
opt-level = 3 # Maximum optimization
|
|
80
|
-
lto = "fat" # Link-time optimization
|
|
81
|
-
codegen-units = 1 # Single codegen unit for better optimization
|
|
82
|
-
panic = "abort" # Remove panic unwinding code
|
|
83
|
-
strip = true # Strip symbols
|
|
84
|
-
debug = false # No debug info
|
|
85
|
-
|
|
86
|
-
# For benchmarking (need some debug info for profiling)
|
|
87
|
-
[profile.bench]
|
|
88
|
-
inherits = "release"
|
|
89
|
-
debug = true
|
|
90
|
-
strip = false
|
|
91
|
-
|
|
92
|
-
# Fast dev builds with optimized dependencies
|
|
93
|
-
[profile.dev]
|
|
94
|
-
opt-level = 0
|
|
95
|
-
debug = true
|
|
96
|
-
|
|
97
|
-
[profile.dev.package."*"]
|
|
98
|
-
opt-level = 3 # Optimize dependencies even in dev
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## When to Use Each
|
|
102
|
-
|
|
103
|
-
| Situation | LTO Setting |
|
|
104
|
-
|-----------|-------------|
|
|
105
|
-
| Development | `false` (fast compiles) |
|
|
106
|
-
| CI builds | `"thin"` (balance) |
|
|
107
|
-
| Release binaries | `"fat"` (max perf) |
|
|
108
|
-
| Libraries (crates.io) | `false` (users choose) |
|
|
109
|
-
|
|
110
|
-
## Measuring Impact
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
# Build without LTO
|
|
114
|
-
cargo build --release
|
|
115
|
-
hyperfine ./target/release/myapp
|
|
116
|
-
|
|
117
|
-
# Build with LTO
|
|
118
|
-
# (after adding lto = "fat" to Cargo.toml)
|
|
119
|
-
cargo build --release
|
|
120
|
-
hyperfine ./target/release/myapp
|
|
121
|
-
|
|
122
|
-
# Compare binary sizes
|
|
123
|
-
ls -la target/release/myapp
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
## See Also
|
|
127
|
-
|
|
128
|
-
- [opt-codegen-units](opt-codegen-units.md) - Use codegen-units = 1
|
|
129
|
-
- [opt-pgo-profile](opt-pgo-profile.md) - Profile-guided optimization
|
|
130
|
-
- [perf-release-profile](perf-release-profile.md) - Full release profile settings
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
# opt-pgo-profile
|
|
2
|
-
|
|
3
|
-
> Use Profile-Guided Optimization (PGO) for maximum performance
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
PGO uses real runtime behavior to guide compiler optimization decisions. By profiling actual workloads, the compiler learns which code paths are hot, optimizing them aggressively while deprioritizing cold paths. This can yield 10-30% performance improvements beyond standard optimizations.
|
|
8
|
-
|
|
9
|
-
## The PGO Process
|
|
10
|
-
|
|
11
|
-
1. **Instrument**: Build with profiling instrumentation
|
|
12
|
-
2. **Profile**: Run representative workloads
|
|
13
|
-
3. **Optimize**: Rebuild using collected profile data
|
|
14
|
-
|
|
15
|
-
## Step-by-Step
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
# Step 1: Build instrumented binary
|
|
19
|
-
RUSTFLAGS="-Cprofile-generate=/tmp/pgo-data" \
|
|
20
|
-
cargo build --release
|
|
21
|
-
|
|
22
|
-
# Step 2: Run representative workloads
|
|
23
|
-
./target/release/my_app < test_data_1.txt
|
|
24
|
-
./target/release/my_app < test_data_2.txt
|
|
25
|
-
./target/release/my_app < typical_workload.txt
|
|
26
|
-
|
|
27
|
-
# Step 3: Merge profile data
|
|
28
|
-
llvm-profdata merge -o /tmp/pgo-data/merged.profdata /tmp/pgo-data
|
|
29
|
-
|
|
30
|
-
# Step 4: Build optimized binary using profile
|
|
31
|
-
RUSTFLAGS="-Cprofile-use=/tmp/pgo-data/merged.profdata" \
|
|
32
|
-
cargo build --release
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Cargo Configuration
|
|
36
|
-
|
|
37
|
-
```toml
|
|
38
|
-
# Cargo.toml
|
|
39
|
-
[profile.release]
|
|
40
|
-
lto = "fat"
|
|
41
|
-
codegen-units = 1
|
|
42
|
-
opt-level = 3
|
|
43
|
-
|
|
44
|
-
# PGO flags set via RUSTFLAGS environment variable
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Build Script
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
#!/bin/bash
|
|
51
|
-
set -e
|
|
52
|
-
|
|
53
|
-
PGO_DIR=/tmp/pgo-$(date +%s)
|
|
54
|
-
|
|
55
|
-
# Clean
|
|
56
|
-
cargo clean
|
|
57
|
-
|
|
58
|
-
# Instrumented build
|
|
59
|
-
echo "Building instrumented binary..."
|
|
60
|
-
RUSTFLAGS="-Cprofile-generate=$PGO_DIR" cargo build --release
|
|
61
|
-
|
|
62
|
-
# Run workloads
|
|
63
|
-
echo "Collecting profile data..."
|
|
64
|
-
./target/release/my_app --benchmark-mode
|
|
65
|
-
./target/release/my_app < test_fixtures/typical.txt
|
|
66
|
-
./target/release/my_app < test_fixtures/stress.txt
|
|
67
|
-
|
|
68
|
-
# Merge profiles
|
|
69
|
-
echo "Merging profile data..."
|
|
70
|
-
llvm-profdata merge -o $PGO_DIR/merged.profdata $PGO_DIR
|
|
71
|
-
|
|
72
|
-
# Optimized build
|
|
73
|
-
echo "Building optimized binary..."
|
|
74
|
-
RUSTFLAGS="-Cprofile-use=$PGO_DIR/merged.profdata" cargo build --release
|
|
75
|
-
|
|
76
|
-
echo "Done! Optimized binary at target/release/my_app"
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## Representative Workloads
|
|
80
|
-
|
|
81
|
-
```rust
|
|
82
|
-
// Create benchmarks that match real usage patterns
|
|
83
|
-
|
|
84
|
-
// Good: actual data samples
|
|
85
|
-
fn profile_workload() {
|
|
86
|
-
for file in real_customer_data_samples() {
|
|
87
|
-
process_file(&file);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Good: synthetic but realistic
|
|
92
|
-
fn profile_synthetic() {
|
|
93
|
-
for _ in 0..10000 {
|
|
94
|
-
let data = generate_realistic_data();
|
|
95
|
-
process(&data);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Bad: artificial microbenchmarks
|
|
100
|
-
fn profile_bad() {
|
|
101
|
-
for _ in 0..1000000 {
|
|
102
|
-
small_operation(); // Doesn't reflect real hot paths
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
## BOLT Post-Link Optimization
|
|
108
|
-
|
|
109
|
-
For even more gains, combine PGO with BOLT:
|
|
110
|
-
|
|
111
|
-
```bash
|
|
112
|
-
# After PGO build, apply BOLT
|
|
113
|
-
llvm-bolt target/release/my_app \
|
|
114
|
-
-o target/release/my_app.bolt \
|
|
115
|
-
-data=perf.data \
|
|
116
|
-
-reorder-blocks=ext-tsp \
|
|
117
|
-
-reorder-functions=hfsort
|
|
118
|
-
|
|
119
|
-
# BOLT can add another 5-15% on top of PGO
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## CI/CD Integration
|
|
123
|
-
|
|
124
|
-
```yaml
|
|
125
|
-
# GitHub Actions example
|
|
126
|
-
jobs:
|
|
127
|
-
pgo-build:
|
|
128
|
-
runs-on: ubuntu-latest
|
|
129
|
-
steps:
|
|
130
|
-
- uses: actions/checkout@v4
|
|
131
|
-
|
|
132
|
-
- name: Install LLVM tools
|
|
133
|
-
run: sudo apt-get install llvm
|
|
134
|
-
|
|
135
|
-
- name: Instrumented build
|
|
136
|
-
run: RUSTFLAGS="-Cprofile-generate=/tmp/pgo" cargo build --release
|
|
137
|
-
|
|
138
|
-
- name: Run profiling workloads
|
|
139
|
-
run: ./scripts/run_profiling_workloads.sh
|
|
140
|
-
|
|
141
|
-
- name: Merge profiles
|
|
142
|
-
run: llvm-profdata merge -o /tmp/pgo/merged.profdata /tmp/pgo
|
|
143
|
-
|
|
144
|
-
- name: Optimized build
|
|
145
|
-
run: RUSTFLAGS="-Cprofile-use=/tmp/pgo/merged.profdata" cargo build --release
|
|
146
|
-
|
|
147
|
-
- name: Upload artifact
|
|
148
|
-
uses: actions/upload-artifact@v4
|
|
149
|
-
with:
|
|
150
|
-
name: optimized-binary
|
|
151
|
-
path: target/release/my_app
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## When to Use PGO
|
|
155
|
-
|
|
156
|
-
| Use PGO | Skip PGO |
|
|
157
|
-
|---------|----------|
|
|
158
|
-
| Production deployments | Development builds |
|
|
159
|
-
| Performance-critical apps | Libraries (users can PGO) |
|
|
160
|
-
| Stable workload patterns | Highly variable workloads |
|
|
161
|
-
| Sufficient profiling data | Quick iteration cycles |
|
|
162
|
-
|
|
163
|
-
## See Also
|
|
164
|
-
|
|
165
|
-
- [opt-lto-release](./opt-lto-release.md) - LTO works well with PGO
|
|
166
|
-
- [opt-codegen-units](./opt-codegen-units.md) - Single codegen unit for PGO
|
|
167
|
-
- [perf-profile-first](./perf-profile-first.md) - Profiling basics
|