agy-superpowers 5.2.2 → 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/rules/scratch-scripts.md +37 -0
- package/template/agent/rules/superpowers.md +4 -51
- 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,181 +0,0 @@
|
|
|
1
|
-
# opt-inline-never-cold
|
|
2
|
-
|
|
3
|
-
> Use `#[inline(never)]` and `#[cold]` for error paths and rarely-executed code
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Inlining error handling code into hot paths wastes instruction cache space and can prevent other optimizations. `#[inline(never)]` keeps cold code out of the hot path. `#[cold]` tells the compiler this branch is unlikely, enabling better branch prediction hints and code layout.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
fn process_data(data: &[u8]) -> Result<Output, Error> {
|
|
13
|
-
if data.is_empty() {
|
|
14
|
-
// Error path inlined into hot function
|
|
15
|
-
return Err(Error::Empty {
|
|
16
|
-
context: format!("Expected data, got empty slice"),
|
|
17
|
-
suggestions: vec!["Check input", "Validate before calling"],
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Hot path - now polluted with error construction code
|
|
22
|
-
do_processing(data)
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Good
|
|
27
|
-
|
|
28
|
-
```rust
|
|
29
|
-
fn process_data(data: &[u8]) -> Result<Output, Error> {
|
|
30
|
-
if data.is_empty() {
|
|
31
|
-
return Err(empty_data_error()); // Cold path stays small
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
do_processing(data)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
#[cold]
|
|
38
|
-
#[inline(never)]
|
|
39
|
-
fn empty_data_error() -> Error {
|
|
40
|
-
Error::Empty {
|
|
41
|
-
context: format!("Expected data, got empty slice"),
|
|
42
|
-
suggestions: vec!["Check input", "Validate before calling"],
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## #[cold] for Unlikely Branches
|
|
48
|
-
|
|
49
|
-
```rust
|
|
50
|
-
fn parse_value(input: &str) -> Result<i32, ParseError> {
|
|
51
|
-
match input.parse() {
|
|
52
|
-
Ok(n) => Ok(n),
|
|
53
|
-
Err(e) => cold_parse_error(input, e),
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
#[cold]
|
|
58
|
-
fn cold_parse_error(input: &str, e: std::num::ParseIntError) -> Result<i32, ParseError> {
|
|
59
|
-
Err(ParseError {
|
|
60
|
-
input: input.to_string(),
|
|
61
|
-
source: e,
|
|
62
|
-
})
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
## Panic Paths
|
|
67
|
-
|
|
68
|
-
```rust
|
|
69
|
-
fn get_index(&self, idx: usize) -> &T {
|
|
70
|
-
if idx >= self.len {
|
|
71
|
-
cold_out_of_bounds(idx, self.len);
|
|
72
|
-
}
|
|
73
|
-
unsafe { self.ptr.add(idx).as_ref().unwrap() }
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
#[cold]
|
|
77
|
-
#[inline(never)]
|
|
78
|
-
fn cold_out_of_bounds(idx: usize, len: usize) -> ! {
|
|
79
|
-
panic!("index {} out of bounds for length {}", idx, len);
|
|
80
|
-
}
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## Error Construction Functions
|
|
84
|
-
|
|
85
|
-
```rust
|
|
86
|
-
// Keep error construction out of hot path
|
|
87
|
-
impl MyError {
|
|
88
|
-
#[cold]
|
|
89
|
-
pub fn io_error(source: std::io::Error, path: &Path) -> Self {
|
|
90
|
-
MyError::Io {
|
|
91
|
-
source,
|
|
92
|
-
path: path.to_path_buf(),
|
|
93
|
-
context: get_context(),
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
#[cold]
|
|
98
|
-
pub fn validation_error(msg: &str, field: &str) -> Self {
|
|
99
|
-
MyError::Validation {
|
|
100
|
-
message: msg.to_string(),
|
|
101
|
-
field: field.to_string(),
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
fn read_config(path: &Path) -> Result<Config, MyError> {
|
|
107
|
-
std::fs::read_to_string(path)
|
|
108
|
-
.map_err(|e| MyError::io_error(e, path))?
|
|
109
|
-
.parse()
|
|
110
|
-
.map_err(|e| MyError::parse_error(e))
|
|
111
|
-
}
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
## likely/unlikely Hints
|
|
115
|
-
|
|
116
|
-
```rust
|
|
117
|
-
// Nightly: intrinsics for branch hints
|
|
118
|
-
#![feature(core_intrinsics)]
|
|
119
|
-
use std::intrinsics::{likely, unlikely};
|
|
120
|
-
|
|
121
|
-
fn process(data: Option<&Data>) -> Result<Output, Error> {
|
|
122
|
-
if unlikely(data.is_none()) {
|
|
123
|
-
return cold_none_error();
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
let data = data.unwrap();
|
|
127
|
-
|
|
128
|
-
if likely(data.is_valid()) {
|
|
129
|
-
fast_process(data)
|
|
130
|
-
} else {
|
|
131
|
-
slow_validate_and_process(data)
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Stable alternative: structure code so hot path is "fall through"
|
|
136
|
-
fn process(data: Option<&Data>) -> Result<Output, Error> {
|
|
137
|
-
let data = match data {
|
|
138
|
-
Some(d) => d,
|
|
139
|
-
None => return cold_none_error(), // Early return = unlikely hint
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
// Compiler assumes code after early returns is "hot"
|
|
143
|
-
fast_process(data)
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
## Pattern: Extract Cold Code
|
|
148
|
-
|
|
149
|
-
```rust
|
|
150
|
-
// Before: cold code inline
|
|
151
|
-
fn hot_function(x: i32) -> i32 {
|
|
152
|
-
if x < 0 {
|
|
153
|
-
log::error!("Negative value: {}", x);
|
|
154
|
-
eprintln!("Debug info: {:?}", std::backtrace::Backtrace::capture());
|
|
155
|
-
return 0;
|
|
156
|
-
}
|
|
157
|
-
x * 2
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// After: cold code extracted
|
|
161
|
-
fn hot_function(x: i32) -> i32 {
|
|
162
|
-
if x < 0 {
|
|
163
|
-
return handle_negative(x);
|
|
164
|
-
}
|
|
165
|
-
x * 2
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
#[cold]
|
|
169
|
-
#[inline(never)]
|
|
170
|
-
fn handle_negative(x: i32) -> i32 {
|
|
171
|
-
log::error!("Negative value: {}", x);
|
|
172
|
-
eprintln!("Debug info: {:?}", std::backtrace::Backtrace::capture());
|
|
173
|
-
0
|
|
174
|
-
}
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
## See Also
|
|
178
|
-
|
|
179
|
-
- [opt-inline-small](./opt-inline-small.md) - Inlining for hot code
|
|
180
|
-
- [opt-inline-always-rare](./opt-inline-always-rare.md) - Forced inlining
|
|
181
|
-
- [err-result-over-panic](./err-result-over-panic.md) - Error handling patterns
|
|
@@ -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
|