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,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
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
# proj-bin-dir
|
|
2
|
-
|
|
3
|
-
> Put multiple binaries in src/bin/
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
When a crate produces multiple binaries, placing them in `src/bin/` keeps the project organized. Each file becomes a separate binary target automatically, without manual `Cargo.toml` configuration.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
my-project/
|
|
13
|
-
├── Cargo.toml # Complex [[bin]] sections for each binary
|
|
14
|
-
├── src/
|
|
15
|
-
│ ├── main.rs # Which binary is this?
|
|
16
|
-
│ ├── server.rs # Is this a module or binary?
|
|
17
|
-
│ ├── cli.rs # Unclear
|
|
18
|
-
│ └── lib.rs
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
```toml
|
|
22
|
-
# Cargo.toml - verbose and error-prone
|
|
23
|
-
[[bin]]
|
|
24
|
-
name = "server"
|
|
25
|
-
path = "src/server.rs"
|
|
26
|
-
|
|
27
|
-
[[bin]]
|
|
28
|
-
name = "cli"
|
|
29
|
-
path = "src/cli.rs"
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Good
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
my-project/
|
|
36
|
-
├── Cargo.toml # Clean, no [[bin]] needed
|
|
37
|
-
├── src/
|
|
38
|
-
│ ├── lib.rs # Shared library code
|
|
39
|
-
│ └── bin/
|
|
40
|
-
│ ├── server.rs # Binary: my-project-server (or just server)
|
|
41
|
-
│ └── cli.rs # Binary: my-project-cli (or just cli)
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Each file in `src/bin/` automatically becomes a binary named after the file.
|
|
45
|
-
|
|
46
|
-
## Running Binaries
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
# Run specific binary
|
|
50
|
-
cargo run --bin server
|
|
51
|
-
cargo run --bin cli
|
|
52
|
-
|
|
53
|
-
# Build specific binary
|
|
54
|
-
cargo build --bin server
|
|
55
|
-
|
|
56
|
-
# Build all binaries
|
|
57
|
-
cargo build --bins
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## Pattern: Binary with Multiple Files
|
|
61
|
-
|
|
62
|
-
For complex binaries, use directories:
|
|
63
|
-
|
|
64
|
-
```
|
|
65
|
-
src/
|
|
66
|
-
├── lib.rs
|
|
67
|
-
└── bin/
|
|
68
|
-
├── server/
|
|
69
|
-
│ ├── main.rs # Entry point
|
|
70
|
-
│ ├── config.rs # Server-specific module
|
|
71
|
-
│ └── handlers.rs
|
|
72
|
-
└── cli/
|
|
73
|
-
├── main.rs
|
|
74
|
-
└── commands.rs
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## Pattern: Shared Library Code
|
|
78
|
-
|
|
79
|
-
```rust
|
|
80
|
-
// src/lib.rs - Shared code
|
|
81
|
-
pub mod config;
|
|
82
|
-
pub mod database;
|
|
83
|
-
pub mod models;
|
|
84
|
-
|
|
85
|
-
// src/bin/server.rs - Server binary
|
|
86
|
-
use my_project::{config, database, models};
|
|
87
|
-
|
|
88
|
-
fn main() {
|
|
89
|
-
let config = config::load();
|
|
90
|
-
let db = database::connect(&config);
|
|
91
|
-
// ...
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// src/bin/cli.rs - CLI binary
|
|
95
|
-
use my_project::{config, models};
|
|
96
|
-
|
|
97
|
-
fn main() {
|
|
98
|
-
let config = config::load();
|
|
99
|
-
// CLI logic using shared code
|
|
100
|
-
}
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
## Binary Naming
|
|
104
|
-
|
|
105
|
-
| File Path | Binary Name |
|
|
106
|
-
|-----------|-------------|
|
|
107
|
-
| `src/main.rs` | `my-project` (crate name) |
|
|
108
|
-
| `src/bin/server.rs` | `server` |
|
|
109
|
-
| `src/bin/my-cli.rs` | `my-cli` |
|
|
110
|
-
| `src/bin/server/main.rs` | `server` |
|
|
111
|
-
|
|
112
|
-
## Explicit Configuration
|
|
113
|
-
|
|
114
|
-
When you need custom settings:
|
|
115
|
-
|
|
116
|
-
```toml
|
|
117
|
-
[[bin]]
|
|
118
|
-
name = "my-server"
|
|
119
|
-
path = "src/bin/server.rs"
|
|
120
|
-
required-features = ["server"]
|
|
121
|
-
|
|
122
|
-
[[bin]]
|
|
123
|
-
name = "my-cli"
|
|
124
|
-
path = "src/bin/cli.rs"
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
## Pattern: Default Binary
|
|
128
|
-
|
|
129
|
-
```toml
|
|
130
|
-
# src/main.rs is the default binary
|
|
131
|
-
# Additional binaries in src/bin/
|
|
132
|
-
|
|
133
|
-
[package]
|
|
134
|
-
name = "my-tool"
|
|
135
|
-
default-run = "my-tool" # Or specify another
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## See Also
|
|
139
|
-
|
|
140
|
-
- [proj-lib-main-split](./proj-lib-main-split.md) - Keep main.rs minimal
|
|
141
|
-
- [proj-workspace-large](./proj-workspace-large.md) - Workspace for larger projects
|
|
142
|
-
- [proj-flat-small](./proj-flat-small.md) - Simple project structure
|