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,150 +0,0 @@
|
|
|
1
|
-
# perf-extend-batch
|
|
2
|
-
|
|
3
|
-
> Use extend for batch insertions
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
`extend()` can pre-allocate capacity for the incoming elements and insert them in a single operation. Individual `push()` calls may trigger multiple reallocations as the collection grows. For adding multiple elements, `extend()` is both faster and clearer.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// Multiple potential reallocations
|
|
13
|
-
fn collect_results(sources: Vec<Source>) -> Vec<Result> {
|
|
14
|
-
let mut results = Vec::new();
|
|
15
|
-
|
|
16
|
-
for source in sources {
|
|
17
|
-
for result in source.get_results() {
|
|
18
|
-
results.push(result); // May reallocate
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
results
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Loop with push for known data
|
|
25
|
-
fn build_list() -> Vec<i32> {
|
|
26
|
-
let mut list = Vec::new();
|
|
27
|
-
for i in 0..1000 {
|
|
28
|
-
list.push(i); // Many reallocations
|
|
29
|
-
}
|
|
30
|
-
list
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Appending another collection
|
|
34
|
-
fn combine(mut a: Vec<i32>, b: Vec<i32>) -> Vec<i32> {
|
|
35
|
-
for item in b {
|
|
36
|
-
a.push(item);
|
|
37
|
-
}
|
|
38
|
-
a
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Good
|
|
43
|
-
|
|
44
|
-
```rust
|
|
45
|
-
// Single extend with size hint
|
|
46
|
-
fn collect_results(sources: Vec<Source>) -> Vec<Result> {
|
|
47
|
-
let mut results = Vec::new();
|
|
48
|
-
|
|
49
|
-
for source in sources {
|
|
50
|
-
results.extend(source.get_results());
|
|
51
|
-
}
|
|
52
|
-
results
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Direct collection from iterator
|
|
56
|
-
fn build_list() -> Vec<i32> {
|
|
57
|
-
(0..1000).collect()
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Extend for combining
|
|
61
|
-
fn combine(mut a: Vec<i32>, b: Vec<i32>) -> Vec<i32> {
|
|
62
|
-
a.extend(b);
|
|
63
|
-
a
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## Extend with Capacity
|
|
68
|
-
|
|
69
|
-
For best performance, combine with `reserve()`:
|
|
70
|
-
|
|
71
|
-
```rust
|
|
72
|
-
fn merge_all(chunks: Vec<Vec<Item>>) -> Vec<Item> {
|
|
73
|
-
// Calculate total size
|
|
74
|
-
let total: usize = chunks.iter().map(|c| c.len()).sum();
|
|
75
|
-
|
|
76
|
-
let mut result = Vec::with_capacity(total);
|
|
77
|
-
for chunk in chunks {
|
|
78
|
-
result.extend(chunk);
|
|
79
|
-
}
|
|
80
|
-
result
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## Extend Methods
|
|
85
|
-
|
|
86
|
-
| Method | Description |
|
|
87
|
-
|--------|-------------|
|
|
88
|
-
| `.extend(iter)` | Add all elements from iterator |
|
|
89
|
-
| `.extend_from_slice(&[T])` | Add from slice (for `Copy` types) |
|
|
90
|
-
| `.append(&mut Vec)` | Move all from another Vec |
|
|
91
|
-
|
|
92
|
-
## Pattern: Building Strings
|
|
93
|
-
|
|
94
|
-
```rust
|
|
95
|
-
// Bad: multiple allocations
|
|
96
|
-
fn build_message(parts: &[&str]) -> String {
|
|
97
|
-
let mut result = String::new();
|
|
98
|
-
for part in parts {
|
|
99
|
-
result.push_str(part); // May reallocate
|
|
100
|
-
}
|
|
101
|
-
result
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Good: extend with known parts
|
|
105
|
-
fn build_message(parts: &[&str]) -> String {
|
|
106
|
-
let total_len: usize = parts.iter().map(|s| s.len()).sum();
|
|
107
|
-
let mut result = String::with_capacity(total_len);
|
|
108
|
-
for part in parts {
|
|
109
|
-
result.push_str(part);
|
|
110
|
-
}
|
|
111
|
-
result
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Better: collect/join
|
|
115
|
-
fn build_message(parts: &[&str]) -> String {
|
|
116
|
-
parts.concat() // or parts.join("")
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## HashMap/HashSet Extend
|
|
121
|
-
|
|
122
|
-
```rust
|
|
123
|
-
use std::collections::HashMap;
|
|
124
|
-
|
|
125
|
-
// Extend from iterator of tuples
|
|
126
|
-
fn merge_maps(mut base: HashMap<String, i32>, other: HashMap<String, i32>) -> HashMap<String, i32> {
|
|
127
|
-
base.extend(other); // Moves entries from other
|
|
128
|
-
base
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Extend from iterator
|
|
132
|
-
let mut set = HashSet::new();
|
|
133
|
-
set.extend(items.iter().map(|i| i.id));
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
## Performance
|
|
137
|
-
|
|
138
|
-
| Operation | Allocations | Complexity |
|
|
139
|
-
|-----------|-------------|------------|
|
|
140
|
-
| N × `push()` | O(log N) | O(N) amortized |
|
|
141
|
-
| `extend(iter)` | O(1)* | O(N) |
|
|
142
|
-
| `with_capacity` + `extend` | 1 | O(N) |
|
|
143
|
-
|
|
144
|
-
*When iterator provides accurate `size_hint()`
|
|
145
|
-
|
|
146
|
-
## See Also
|
|
147
|
-
|
|
148
|
-
- [mem-with-capacity](./mem-with-capacity.md) - Pre-allocation
|
|
149
|
-
- [perf-drain-reuse](./perf-drain-reuse.md) - Reusing allocations
|
|
150
|
-
- [mem-reuse-collections](./mem-reuse-collections.md) - Collection reuse
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
# perf-iter-lazy
|
|
2
|
-
|
|
3
|
-
> Keep iterators lazy, collect only when needed
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Rust iterators are lazy—they compute values on demand. This enables single-pass processing, avoids intermediate allocations, and allows short-circuiting. Calling `.collect()` too early forces evaluation and allocates unnecessarily.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// Collects intermediate results unnecessarily
|
|
13
|
-
fn process(data: Vec<i32>) -> Vec<i32> {
|
|
14
|
-
let filtered: Vec<_> = data.into_iter()
|
|
15
|
-
.filter(|x| *x > 0)
|
|
16
|
-
.collect(); // Unnecessary allocation
|
|
17
|
-
|
|
18
|
-
let mapped: Vec<_> = filtered.into_iter()
|
|
19
|
-
.map(|x| x * 2)
|
|
20
|
-
.collect(); // Another unnecessary allocation
|
|
21
|
-
|
|
22
|
-
mapped.into_iter()
|
|
23
|
-
.take(10)
|
|
24
|
-
.collect()
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Collects before checking existence
|
|
28
|
-
fn has_positive(data: &[i32]) -> bool {
|
|
29
|
-
let positives: Vec<_> = data.iter()
|
|
30
|
-
.filter(|&&x| x > 0)
|
|
31
|
-
.collect(); // Allocates entire filtered result
|
|
32
|
-
|
|
33
|
-
!positives.is_empty()
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Good
|
|
38
|
-
|
|
39
|
-
```rust
|
|
40
|
-
// Single chain, single collect
|
|
41
|
-
fn process(data: Vec<i32>) -> Vec<i32> {
|
|
42
|
-
data.into_iter()
|
|
43
|
-
.filter(|x| *x > 0)
|
|
44
|
-
.map(|x| x * 2)
|
|
45
|
-
.take(10)
|
|
46
|
-
.collect()
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Short-circuits on first match
|
|
50
|
-
fn has_positive(data: &[i32]) -> bool {
|
|
51
|
-
data.iter().any(|&x| x > 0)
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Lazy Iterator Methods
|
|
56
|
-
|
|
57
|
-
These methods return iterators (lazy):
|
|
58
|
-
|
|
59
|
-
| Method | Description |
|
|
60
|
-
|--------|-------------|
|
|
61
|
-
| `.filter()` | Keep matching elements |
|
|
62
|
-
| `.map()` | Transform elements |
|
|
63
|
-
| `.take(n)` | Limit to n elements |
|
|
64
|
-
| `.skip(n)` | Skip first n elements |
|
|
65
|
-
| `.zip()` | Pair with another iterator |
|
|
66
|
-
| `.chain()` | Concatenate iterators |
|
|
67
|
-
| `.flat_map()` | Map and flatten |
|
|
68
|
-
| `.enumerate()` | Add index |
|
|
69
|
-
|
|
70
|
-
## Consuming Methods
|
|
71
|
-
|
|
72
|
-
These methods consume the iterator (evaluate immediately):
|
|
73
|
-
|
|
74
|
-
| Method | Description |
|
|
75
|
-
|--------|-------------|
|
|
76
|
-
| `.collect()` | Gather into collection |
|
|
77
|
-
| `.for_each()` | Execute side effect |
|
|
78
|
-
| `.count()` | Count elements |
|
|
79
|
-
| `.sum()` | Sum elements |
|
|
80
|
-
| `.fold()` | Accumulate value |
|
|
81
|
-
| `.any()` | Check if any match |
|
|
82
|
-
| `.all()` | Check if all match |
|
|
83
|
-
| `.find()` | Find first match |
|
|
84
|
-
|
|
85
|
-
## Short-Circuit Benefits
|
|
86
|
-
|
|
87
|
-
```rust
|
|
88
|
-
// Without lazy: processes ALL items
|
|
89
|
-
let found: Vec<_> = items.iter()
|
|
90
|
-
.filter(|x| expensive_check(x))
|
|
91
|
-
.collect();
|
|
92
|
-
let result = found.first();
|
|
93
|
-
|
|
94
|
-
// With lazy: stops at first match
|
|
95
|
-
let result = items.iter()
|
|
96
|
-
.find(|x| expensive_check(x));
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## Pattern: Process Without Collecting
|
|
100
|
-
|
|
101
|
-
```rust
|
|
102
|
-
// Print all matches without allocating
|
|
103
|
-
data.iter()
|
|
104
|
-
.filter(|x| x.is_valid())
|
|
105
|
-
.for_each(|x| println!("{}", x));
|
|
106
|
-
|
|
107
|
-
// Count without collecting
|
|
108
|
-
let count = data.iter()
|
|
109
|
-
.filter(|x| x.is_valid())
|
|
110
|
-
.count();
|
|
111
|
-
|
|
112
|
-
// Sum without intermediate collection
|
|
113
|
-
let total: i64 = data.iter()
|
|
114
|
-
.filter(|x| x.is_valid())
|
|
115
|
-
.map(|x| x.value as i64)
|
|
116
|
-
.sum();
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
## See Also
|
|
120
|
-
|
|
121
|
-
- [perf-collect-once](./perf-collect-once.md) - Single collect
|
|
122
|
-
- [perf-iter-over-index](./perf-iter-over-index.md) - Prefer iterators
|
|
123
|
-
- [anti-collect-intermediate](./anti-collect-intermediate.md) - Anti-pattern
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
# perf-iter-over-index
|
|
2
|
-
|
|
3
|
-
> Prefer iterators over manual indexing
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Iterators are the idiomatic way to traverse collections in Rust. They enable bounds check elimination, SIMD auto-vectorization, and cleaner code. Manual indexing (`for i in 0..len`) often prevents these optimizations and introduces off-by-one error risks.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// Manual indexing - bounds checked every iteration
|
|
13
|
-
fn sum_squares(data: &[i32]) -> i64 {
|
|
14
|
-
let mut sum = 0i64;
|
|
15
|
-
for i in 0..data.len() {
|
|
16
|
-
sum += (data[i] as i64) * (data[i] as i64);
|
|
17
|
-
}
|
|
18
|
-
sum
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Index-based iteration with multiple collections
|
|
22
|
-
fn dot_product(a: &[f64], b: &[f64]) -> f64 {
|
|
23
|
-
let mut sum = 0.0;
|
|
24
|
-
for i in 0..a.len().min(b.len()) {
|
|
25
|
-
sum += a[i] * b[i];
|
|
26
|
-
}
|
|
27
|
-
sum
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Mutating with indices
|
|
31
|
-
fn double_values(data: &mut [i32]) {
|
|
32
|
-
for i in 0..data.len() {
|
|
33
|
-
data[i] *= 2;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Good
|
|
39
|
-
|
|
40
|
-
```rust
|
|
41
|
-
// Iterator - bounds checks eliminated, SIMD-friendly
|
|
42
|
-
fn sum_squares(data: &[i32]) -> i64 {
|
|
43
|
-
data.iter()
|
|
44
|
-
.map(|&x| (x as i64) * (x as i64))
|
|
45
|
-
.sum()
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Zip iterators - no manual length handling
|
|
49
|
-
fn dot_product(a: &[f64], b: &[f64]) -> f64 {
|
|
50
|
-
a.iter()
|
|
51
|
-
.zip(b.iter())
|
|
52
|
-
.map(|(&x, &y)| x * y)
|
|
53
|
-
.sum()
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Mutable iteration
|
|
57
|
-
fn double_values(data: &mut [i32]) {
|
|
58
|
-
for x in data.iter_mut() {
|
|
59
|
-
*x *= 2;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## When Indexing Is Needed
|
|
65
|
-
|
|
66
|
-
Sometimes you genuinely need indices:
|
|
67
|
-
|
|
68
|
-
```rust
|
|
69
|
-
// Need the index for output or processing
|
|
70
|
-
for (i, value) in data.iter().enumerate() {
|
|
71
|
-
println!("Index {}: {}", i, value);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Non-sequential access patterns
|
|
75
|
-
fn interleave(data: &mut [i32]) {
|
|
76
|
-
let mid = data.len() / 2;
|
|
77
|
-
for i in 0..mid {
|
|
78
|
-
data.swap(i * 2, mid + i);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## Performance Comparison
|
|
84
|
-
|
|
85
|
-
| Pattern | Bounds Checks | SIMD Potential | Clarity |
|
|
86
|
-
|---------|---------------|----------------|---------|
|
|
87
|
-
| `for i in 0..len` | Every access | Limited | Medium |
|
|
88
|
-
| `for &x in slice` | None | High | High |
|
|
89
|
-
| `.iter().enumerate()` | None | Medium | High |
|
|
90
|
-
| `get_unchecked` | None (unsafe) | High | Low |
|
|
91
|
-
|
|
92
|
-
## Iterator Advantages
|
|
93
|
-
|
|
94
|
-
```rust
|
|
95
|
-
// Chaining operations - single pass
|
|
96
|
-
let result: Vec<_> = data.iter()
|
|
97
|
-
.filter(|x| **x > 0)
|
|
98
|
-
.map(|x| x * 2)
|
|
99
|
-
.collect();
|
|
100
|
-
|
|
101
|
-
// Early termination optimized
|
|
102
|
-
let found = data.iter().any(|&x| x == target);
|
|
103
|
-
|
|
104
|
-
// Parallel iteration (with rayon)
|
|
105
|
-
use rayon::prelude::*;
|
|
106
|
-
let sum: i64 = data.par_iter().map(|&x| x as i64).sum();
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## See Also
|
|
110
|
-
|
|
111
|
-
- [perf-iter-lazy](./perf-iter-lazy.md) - Keep iterators lazy
|
|
112
|
-
- [opt-bounds-check](./opt-bounds-check.md) - Bounds check elimination
|
|
113
|
-
- [anti-index-over-iter](./anti-index-over-iter.md) - Anti-pattern
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
# perf-profile-first
|
|
2
|
-
|
|
3
|
-
> Profile before optimizing
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Intuition about performance is often wrong. The code you think is slow frequently isn't, while actual bottlenecks hide in unexpected places. Profiling shows you exactly where time is spent, preventing wasted effort on optimizations that don't matter.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// Optimizing without measuring
|
|
13
|
-
fn process(data: &[Item]) -> Vec<Output> {
|
|
14
|
-
// "I bet this clone is slow..."
|
|
15
|
-
let cloned: Vec<_> = data.iter().cloned().collect();
|
|
16
|
-
|
|
17
|
-
// Actually, 99% of time is spent here:
|
|
18
|
-
cloned.iter().map(|x| expensive_computation(x)).collect()
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Over-engineering rarely-called code
|
|
22
|
-
#[inline(always)]
|
|
23
|
-
fn rarely_called() {
|
|
24
|
-
// This runs once at startup...
|
|
25
|
-
}
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Good
|
|
29
|
-
|
|
30
|
-
```rust
|
|
31
|
-
// 1. Profile first
|
|
32
|
-
// cargo flamegraph --bin myapp
|
|
33
|
-
// cargo instruments -t time --bin myapp (macOS)
|
|
34
|
-
|
|
35
|
-
// 2. Find the actual bottleneck
|
|
36
|
-
// Flamegraph shows expensive_computation takes 95% of time
|
|
37
|
-
|
|
38
|
-
// 3. Optimize the hot spot
|
|
39
|
-
fn process(data: &[Item]) -> Vec<Output> {
|
|
40
|
-
// Clone is fine - only 1% of time
|
|
41
|
-
let cloned: Vec<_> = data.iter().cloned().collect();
|
|
42
|
-
|
|
43
|
-
// Focus optimization HERE
|
|
44
|
-
cloned.par_iter() // Parallelize the expensive part
|
|
45
|
-
.map(|x| expensive_computation(x))
|
|
46
|
-
.collect()
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Profiling Tools
|
|
51
|
-
|
|
52
|
-
### Flamegraphs (Recommended Start)
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
# Install
|
|
56
|
-
cargo install flamegraph
|
|
57
|
-
|
|
58
|
-
# Profile
|
|
59
|
-
cargo flamegraph --bin myapp -- <args>
|
|
60
|
-
|
|
61
|
-
# Opens flamegraph.svg showing call stacks by time
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### perf (Linux)
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
# Record
|
|
68
|
-
perf record -g cargo run --release
|
|
69
|
-
|
|
70
|
-
# Report
|
|
71
|
-
perf report
|
|
72
|
-
|
|
73
|
-
# Or generate flamegraph
|
|
74
|
-
perf script | inferno-collapse-perf | inferno-flamegraph > flamegraph.svg
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Instruments (macOS)
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
# Install cargo-instruments
|
|
81
|
-
cargo install cargo-instruments
|
|
82
|
-
|
|
83
|
-
# Time profiler
|
|
84
|
-
cargo instruments -t time --release
|
|
85
|
-
|
|
86
|
-
# Allocations profiler
|
|
87
|
-
cargo instruments -t alloc --release
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### DHAT (Heap Profiling)
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
# In your code
|
|
94
|
-
#[global_allocator]
|
|
95
|
-
static ALLOC: dhat::Alloc = dhat::Alloc;
|
|
96
|
-
|
|
97
|
-
fn main() {
|
|
98
|
-
let _profiler = dhat::Profiler::new_heap();
|
|
99
|
-
// ... your code
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
# Run and get allocation report
|
|
103
|
-
cargo run --release
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### criterion (Micro-benchmarks)
|
|
107
|
-
|
|
108
|
-
```rust
|
|
109
|
-
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
|
110
|
-
|
|
111
|
-
fn bench_my_function(c: &mut Criterion) {
|
|
112
|
-
c.bench_function("my_function", |b| {
|
|
113
|
-
b.iter(|| my_function(black_box(input)))
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
criterion_group!(benches, bench_my_function);
|
|
118
|
-
criterion_main!(benches);
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
## What to Look For
|
|
122
|
-
|
|
123
|
-
```
|
|
124
|
-
Flamegraph Reading:
|
|
125
|
-
├── Width = time spent
|
|
126
|
-
├── Height = call stack depth
|
|
127
|
-
└── Look for:
|
|
128
|
-
├── Wide bars (time hogs)
|
|
129
|
-
├── malloc/free (allocation heavy)
|
|
130
|
-
├── memcpy (copying data)
|
|
131
|
-
└── Unexpected functions taking time
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## Common Findings
|
|
135
|
-
|
|
136
|
-
```rust
|
|
137
|
-
// Finding: HashMap operations are slow
|
|
138
|
-
// Fix: Use FxHashMap or AHashMap for non-crypto hashing
|
|
139
|
-
|
|
140
|
-
// Finding: String allocation in hot loop
|
|
141
|
-
// Fix: Pre-allocate with capacity, use &str
|
|
142
|
-
|
|
143
|
-
// Finding: Clone in hot path
|
|
144
|
-
// Fix: Use references or Cow
|
|
145
|
-
|
|
146
|
-
// Finding: Bounds checks visible in profile
|
|
147
|
-
// Fix: Use iterators instead of indexing
|
|
148
|
-
|
|
149
|
-
// Finding: Lock contention
|
|
150
|
-
// Fix: Reduce critical section, use RwLock, or partition data
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
## Optimization Workflow
|
|
154
|
-
|
|
155
|
-
```
|
|
156
|
-
1. Write correct code first
|
|
157
|
-
2. Write benchmarks for hot paths
|
|
158
|
-
3. Profile under realistic load
|
|
159
|
-
4. Identify actual bottlenecks
|
|
160
|
-
5. Optimize ONE thing
|
|
161
|
-
6. Measure improvement
|
|
162
|
-
7. Repeat if needed
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
## Evidence: Rust Performance Book
|
|
166
|
-
|
|
167
|
-
> "The biggest performance improvements often come from changes to algorithms or data structures, rather than low-level optimizations."
|
|
168
|
-
|
|
169
|
-
> "It is worth understanding which Rust data structures and operations cause allocations, because avoiding them can greatly improve performance."
|
|
170
|
-
|
|
171
|
-
## See Also
|
|
172
|
-
|
|
173
|
-
- [opt-lto-release](opt-lto-release.md) - Enable LTO for release builds
|
|
174
|
-
- [test-criterion-bench](test-criterion-bench.md) - Use criterion for benchmarking
|
|
175
|
-
- [anti-premature-optimize](anti-premature-optimize.md) - Don't optimize without data
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
# perf-release-profile
|
|
2
|
-
|
|
3
|
-
> Optimize release profile settings
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
The default release profile prioritizes compile speed over runtime performance. For production binaries, tuning the release profile can yield significant performance improvements (10-40% in some cases) at the cost of longer compile times.
|
|
8
|
-
|
|
9
|
-
## Default Profile
|
|
10
|
-
|
|
11
|
-
```toml
|
|
12
|
-
[profile.release]
|
|
13
|
-
opt-level = 3
|
|
14
|
-
debug = false
|
|
15
|
-
lto = false
|
|
16
|
-
codegen-units = 16
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Optimized Profile
|
|
20
|
-
|
|
21
|
-
```toml
|
|
22
|
-
[profile.release]
|
|
23
|
-
opt-level = 3 # Maximum optimization
|
|
24
|
-
lto = "fat" # Full link-time optimization
|
|
25
|
-
codegen-units = 1 # Better optimization, slower compile
|
|
26
|
-
panic = "abort" # Smaller binary, no unwinding
|
|
27
|
-
strip = true # Remove symbols
|
|
28
|
-
|
|
29
|
-
[profile.release.package."*"]
|
|
30
|
-
# Keep dependencies optimized even if main crate changes
|
|
31
|
-
opt-level = 3
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Profile Options
|
|
35
|
-
|
|
36
|
-
| Option | Values | Effect |
|
|
37
|
-
|--------|--------|--------|
|
|
38
|
-
| `opt-level` | 0-3, "s", "z" | Optimization level |
|
|
39
|
-
| `lto` | false, "thin", "fat" | Link-time optimization |
|
|
40
|
-
| `codegen-units` | 1-256 | Parallel compilation units |
|
|
41
|
-
| `panic` | "unwind", "abort" | Panic behavior |
|
|
42
|
-
| `strip` | true, false, "symbols", "debuginfo" | Binary stripping |
|
|
43
|
-
| `debug` | true, false, 0-2 | Debug info level |
|
|
44
|
-
|
|
45
|
-
## Optimization Levels
|
|
46
|
-
|
|
47
|
-
| Level | Description | Use Case |
|
|
48
|
-
|-------|-------------|----------|
|
|
49
|
-
| `0` | No optimization | Debug builds |
|
|
50
|
-
| `1` | Basic optimization | Fast compile |
|
|
51
|
-
| `2` | Most optimizations | Balanced |
|
|
52
|
-
| `3` | All optimizations | Maximum performance |
|
|
53
|
-
| `"s"` | Optimize for size | Embedded |
|
|
54
|
-
| `"z"` | Minimize size | Smallest binary |
|
|
55
|
-
|
|
56
|
-
## LTO Options
|
|
57
|
-
|
|
58
|
-
| Option | Compile Time | Performance | Binary Size |
|
|
59
|
-
|--------|--------------|-------------|-------------|
|
|
60
|
-
| `false` | Fast | Baseline | Larger |
|
|
61
|
-
| `"thin"` | Medium | Good | Smaller |
|
|
62
|
-
| `"fat"` | Slow | Best | Smallest |
|
|
63
|
-
|
|
64
|
-
## Custom Profiles
|
|
65
|
-
|
|
66
|
-
```toml
|
|
67
|
-
# Fast release builds for development
|
|
68
|
-
[profile.release-dev]
|
|
69
|
-
inherits = "release"
|
|
70
|
-
lto = false
|
|
71
|
-
codegen-units = 16
|
|
72
|
-
|
|
73
|
-
# Maximum performance for production
|
|
74
|
-
[profile.release-prod]
|
|
75
|
-
inherits = "release"
|
|
76
|
-
lto = "fat"
|
|
77
|
-
codegen-units = 1
|
|
78
|
-
strip = true
|
|
79
|
-
|
|
80
|
-
# Profiling with symbols
|
|
81
|
-
[profile.profiling]
|
|
82
|
-
inherits = "release"
|
|
83
|
-
debug = true
|
|
84
|
-
strip = false
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
Use with: `cargo build --profile release-prod`
|
|
88
|
-
|
|
89
|
-
## Dev Dependencies Optimization
|
|
90
|
-
|
|
91
|
-
Speed up tests and dev builds:
|
|
92
|
-
|
|
93
|
-
```toml
|
|
94
|
-
[profile.dev]
|
|
95
|
-
opt-level = 0
|
|
96
|
-
|
|
97
|
-
# Optimize dependencies even in dev
|
|
98
|
-
[profile.dev.package."*"]
|
|
99
|
-
opt-level = 3
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Benchmarking Profile
|
|
103
|
-
|
|
104
|
-
```toml
|
|
105
|
-
[profile.bench]
|
|
106
|
-
inherits = "release"
|
|
107
|
-
debug = true # For profiling
|
|
108
|
-
strip = false # Keep symbols for flamegraphs
|
|
109
|
-
lto = "fat" # Consistent with release-prod
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
## Size vs Speed Trade-offs
|
|
113
|
-
|
|
114
|
-
```toml
|
|
115
|
-
# Smallest binary
|
|
116
|
-
[profile.min-size]
|
|
117
|
-
inherits = "release"
|
|
118
|
-
opt-level = "z"
|
|
119
|
-
lto = "fat"
|
|
120
|
-
codegen-units = 1
|
|
121
|
-
panic = "abort"
|
|
122
|
-
strip = true
|
|
123
|
-
|
|
124
|
-
# Balance size and speed
|
|
125
|
-
[profile.balanced]
|
|
126
|
-
inherits = "release"
|
|
127
|
-
opt-level = "s"
|
|
128
|
-
lto = "thin"
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
## Workspace Configuration
|
|
132
|
-
|
|
133
|
-
```toml
|
|
134
|
-
# In workspace Cargo.toml
|
|
135
|
-
[profile.release]
|
|
136
|
-
lto = "fat"
|
|
137
|
-
codegen-units = 1
|
|
138
|
-
|
|
139
|
-
# Override for specific package
|
|
140
|
-
[profile.release.package.fast-compile-lib]
|
|
141
|
-
lto = false
|
|
142
|
-
codegen-units = 16
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
## See Also
|
|
146
|
-
|
|
147
|
-
- [opt-lto-release](./opt-lto-release.md) - LTO details
|
|
148
|
-
- [opt-codegen-units](./opt-codegen-units.md) - Codegen units
|
|
149
|
-
- [opt-pgo-profile](./opt-pgo-profile.md) - Profile-guided optimization
|