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,125 +0,0 @@
|
|
|
1
|
-
# anti-index-over-iter
|
|
2
|
-
|
|
3
|
-
> Don't use indexing when iterators work
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Manual indexing (`for i in 0..len`) requires bounds checks on every access, prevents SIMD optimization, and introduces off-by-one error risks. Iterators eliminate these issues and are more idiomatic Rust.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// Manual indexing - bounds checked every access
|
|
13
|
-
fn sum_squares(data: &[i32]) -> i64 {
|
|
14
|
-
let mut result = 0i64;
|
|
15
|
-
for i in 0..data.len() {
|
|
16
|
-
result += (data[i] as i64) * (data[i] as i64);
|
|
17
|
-
}
|
|
18
|
-
result
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Index-based with multiple arrays
|
|
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
|
-
// Mutation with indices
|
|
31
|
-
fn normalize(data: &mut [f64]) {
|
|
32
|
-
let max = data.iter().cloned().fold(0.0, f64::max);
|
|
33
|
-
for i in 0..data.len() {
|
|
34
|
-
data[i] /= max;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Good
|
|
40
|
-
|
|
41
|
-
```rust
|
|
42
|
-
// Iterator - no bounds checks, SIMD-friendly
|
|
43
|
-
fn sum_squares(data: &[i32]) -> i64 {
|
|
44
|
-
data.iter()
|
|
45
|
-
.map(|&x| (x as i64) * (x as i64))
|
|
46
|
-
.sum()
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Zip - handles length mismatch automatically
|
|
50
|
-
fn dot_product(a: &[f64], b: &[f64]) -> f64 {
|
|
51
|
-
a.iter()
|
|
52
|
-
.zip(b.iter())
|
|
53
|
-
.map(|(&x, &y)| x * y)
|
|
54
|
-
.sum()
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Mutable iteration
|
|
58
|
-
fn normalize(data: &mut [f64]) {
|
|
59
|
-
let max = data.iter().cloned().fold(0.0, f64::max);
|
|
60
|
-
for x in data.iter_mut() {
|
|
61
|
-
*x /= max;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
## When Indices Are Needed
|
|
67
|
-
|
|
68
|
-
Sometimes you genuinely need indices:
|
|
69
|
-
|
|
70
|
-
```rust
|
|
71
|
-
// Need index in output
|
|
72
|
-
for (i, item) in items.iter().enumerate() {
|
|
73
|
-
println!("{}: {}", i, item);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Non-sequential access
|
|
77
|
-
for i in (0..len).step_by(2) {
|
|
78
|
-
swap(&mut data[i], &mut data[i + 1]);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Multi-dimensional iteration
|
|
82
|
-
for i in 0..rows {
|
|
83
|
-
for j in 0..cols {
|
|
84
|
-
matrix[i][j] = i * cols + j;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
## Comparison
|
|
90
|
-
|
|
91
|
-
| Pattern | Bounds Checks | SIMD | Safety |
|
|
92
|
-
|---------|---------------|------|--------|
|
|
93
|
-
| `for i in 0..len { data[i] }` | Every access | Limited | Off-by-one risk |
|
|
94
|
-
| `for x in &data` | None | Good | Safe |
|
|
95
|
-
| `for x in data.iter()` | None | Good | Safe |
|
|
96
|
-
| `data.iter().enumerate()` | None | Good | Safe |
|
|
97
|
-
|
|
98
|
-
## Common Conversions
|
|
99
|
-
|
|
100
|
-
| Index Pattern | Iterator Pattern |
|
|
101
|
-
|---------------|------------------|
|
|
102
|
-
| `for i in 0..v.len()` | `for x in &v` |
|
|
103
|
-
| `v[0]` | `v.first()` |
|
|
104
|
-
| `v[v.len()-1]` | `v.last()` |
|
|
105
|
-
| `for i in 0..a.len() { a[i] + b[i] }` | `a.iter().zip(&b)` |
|
|
106
|
-
| `for i in 0..v.len() { v[i] *= 2 }` | `for x in &mut v { *x *= 2 }` |
|
|
107
|
-
|
|
108
|
-
## Performance Note
|
|
109
|
-
|
|
110
|
-
```rust
|
|
111
|
-
// Iterator version can auto-vectorize
|
|
112
|
-
let sum: i32 = data.iter().sum();
|
|
113
|
-
|
|
114
|
-
// Manual indexing prevents vectorization
|
|
115
|
-
let mut sum = 0;
|
|
116
|
-
for i in 0..data.len() {
|
|
117
|
-
sum += data[i];
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
## See Also
|
|
122
|
-
|
|
123
|
-
- [perf-iter-over-index](./perf-iter-over-index.md) - Performance details
|
|
124
|
-
- [opt-bounds-check](./opt-bounds-check.md) - Bounds check elimination
|
|
125
|
-
- [perf-iter-lazy](./perf-iter-lazy.md) - Lazy iterators
|
package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
# anti-lock-across-await
|
|
2
|
-
|
|
3
|
-
> Don't hold locks across await points
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Holding a `Mutex` or `RwLock` guard across an `.await` causes the lock to be held while the task is suspended. Other tasks waiting for the lock block indefinitely. With `std::sync::Mutex`, this is even worse—it can deadlock the entire runtime.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
use std::sync::Mutex;
|
|
13
|
-
use tokio::sync::Mutex as AsyncMutex;
|
|
14
|
-
|
|
15
|
-
// DEADLOCK RISK: std::sync::Mutex held across await
|
|
16
|
-
async fn bad_std_mutex(data: &Mutex<Vec<i32>>) {
|
|
17
|
-
let mut guard = data.lock().unwrap();
|
|
18
|
-
do_async_work().await; // Lock held during await!
|
|
19
|
-
guard.push(42);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// BLOCKS OTHER TASKS: tokio Mutex held across await
|
|
23
|
-
async fn bad_async_mutex(data: &AsyncMutex<Vec<i32>>) {
|
|
24
|
-
let mut guard = data.lock().await;
|
|
25
|
-
slow_network_call().await; // Lock held for entire call!
|
|
26
|
-
guard.push(42);
|
|
27
|
-
}
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Good
|
|
31
|
-
|
|
32
|
-
```rust
|
|
33
|
-
use std::sync::Mutex;
|
|
34
|
-
use tokio::sync::Mutex as AsyncMutex;
|
|
35
|
-
|
|
36
|
-
// Release lock before await
|
|
37
|
-
async fn good_approach(data: &Mutex<Vec<i32>>) {
|
|
38
|
-
let value = {
|
|
39
|
-
let guard = data.lock().unwrap();
|
|
40
|
-
guard.last().copied() // Extract what you need
|
|
41
|
-
}; // Lock released here
|
|
42
|
-
|
|
43
|
-
let result = do_async_work(value).await;
|
|
44
|
-
|
|
45
|
-
{
|
|
46
|
-
let mut guard = data.lock().unwrap();
|
|
47
|
-
guard.push(result);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Minimize lock scope with async mutex
|
|
52
|
-
async fn good_async_mutex(data: &AsyncMutex<Vec<i32>>, item: i32) {
|
|
53
|
-
// Quick lock, quick release
|
|
54
|
-
data.lock().await.push(item);
|
|
55
|
-
|
|
56
|
-
// Async work without lock
|
|
57
|
-
let result = slow_network_call().await;
|
|
58
|
-
|
|
59
|
-
// Quick lock again
|
|
60
|
-
data.lock().await.push(result);
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Pattern: Clone Before Await
|
|
65
|
-
|
|
66
|
-
```rust
|
|
67
|
-
async fn process(data: &AsyncMutex<Config>) -> Result<()> {
|
|
68
|
-
// Clone inside lock scope
|
|
69
|
-
let config = data.lock().await.clone();
|
|
70
|
-
|
|
71
|
-
// Now use config freely across awaits
|
|
72
|
-
let result = fetch_data(&config.url).await?;
|
|
73
|
-
process_result(&config, result).await?;
|
|
74
|
-
|
|
75
|
-
Ok(())
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## Pattern: Restructure to Avoid Lock
|
|
80
|
-
|
|
81
|
-
```rust
|
|
82
|
-
// Instead of locking a shared map
|
|
83
|
-
struct Service {
|
|
84
|
-
data: AsyncMutex<HashMap<String, Data>>,
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Use channels or owned data
|
|
88
|
-
struct BetterService {
|
|
89
|
-
// Each task owns its data via channels
|
|
90
|
-
sender: mpsc::Sender<Request>,
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
impl BetterService {
|
|
94
|
-
async fn request(&self, key: String) -> Data {
|
|
95
|
-
let (tx, rx) = oneshot::channel();
|
|
96
|
-
self.sender.send(Request { key, respond: tx }).await?;
|
|
97
|
-
rx.await?
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## What Can Cross Await
|
|
103
|
-
|
|
104
|
-
| Type | Safe Across Await? |
|
|
105
|
-
|------|--------------------|
|
|
106
|
-
| `std::sync::Mutex` guard | **NO** - can deadlock |
|
|
107
|
-
| `std::sync::RwLock` guard | **NO** - can deadlock |
|
|
108
|
-
| `tokio::sync::Mutex` guard | Allowed but blocks tasks |
|
|
109
|
-
| `tokio::sync::RwLock` guard | Allowed but blocks tasks |
|
|
110
|
-
| Owned values | Yes |
|
|
111
|
-
| `Arc<T>` | Yes |
|
|
112
|
-
| References | Depends on lifetime |
|
|
113
|
-
|
|
114
|
-
## Detection
|
|
115
|
-
|
|
116
|
-
```toml
|
|
117
|
-
# Cargo.toml
|
|
118
|
-
[lints.clippy]
|
|
119
|
-
await_holding_lock = "deny"
|
|
120
|
-
await_holding_refcell_ref = "deny"
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
## See Also
|
|
124
|
-
|
|
125
|
-
- [async-no-lock-await](./async-no-lock-await.md) - Async lock patterns
|
|
126
|
-
- [async-clone-before-await](./async-clone-before-await.md) - Clone pattern
|
|
127
|
-
- [own-mutex-interior](./own-mutex-interior.md) - Mutex usage
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
# anti-over-abstraction
|
|
2
|
-
|
|
3
|
-
> Don't over-abstract with excessive generics
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Generics and traits are powerful but come at a cost: compile times, binary size, and cognitive load. Over-abstraction—making everything generic "for flexibility"—often adds complexity without benefit. Start concrete; generalize when you have real use cases.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// Overly generic for a simple function
|
|
13
|
-
fn add<T, U, R>(a: T, b: U) -> R
|
|
14
|
-
where
|
|
15
|
-
T: Into<R>,
|
|
16
|
-
U: Into<R>,
|
|
17
|
-
R: std::ops::Add<Output = R>,
|
|
18
|
-
{
|
|
19
|
-
a.into() + b.into()
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Just call add(1, 2) - why make it this complex?
|
|
23
|
-
|
|
24
|
-
// Trait explosion
|
|
25
|
-
trait Readable {}
|
|
26
|
-
trait Writable {}
|
|
27
|
-
trait ReadWritable: Readable + Writable {}
|
|
28
|
-
trait AsyncReadable {}
|
|
29
|
-
trait AsyncWritable {}
|
|
30
|
-
trait AsyncReadWritable: AsyncReadable + AsyncWritable {}
|
|
31
|
-
|
|
32
|
-
// Abstract factory pattern (Java flashback)
|
|
33
|
-
trait Factory<T> {
|
|
34
|
-
fn create(&self) -> T;
|
|
35
|
-
}
|
|
36
|
-
trait FactoryFactory<F: Factory<T>, T> {
|
|
37
|
-
fn create_factory(&self) -> F;
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Good
|
|
42
|
-
|
|
43
|
-
```rust
|
|
44
|
-
// Concrete implementation - clear and simple
|
|
45
|
-
fn add_i32(a: i32, b: i32) -> i32 {
|
|
46
|
-
a + b
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Generic when actually needed (e.g., library code)
|
|
50
|
-
fn add<T: std::ops::Add<Output = T>>(a: T, b: T) -> T {
|
|
51
|
-
a + b
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Simple traits for actual polymorphism needs
|
|
55
|
-
trait Storage {
|
|
56
|
-
fn save(&self, key: &str, value: &[u8]) -> Result<(), Error>;
|
|
57
|
-
fn load(&self, key: &str) -> Result<Vec<u8>, Error>;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Concrete types first
|
|
61
|
-
struct FileStorage { path: PathBuf }
|
|
62
|
-
struct MemoryStorage { data: HashMap<String, Vec<u8>> }
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Signs of Over-Abstraction
|
|
66
|
-
|
|
67
|
-
| Sign | Symptom |
|
|
68
|
-
|------|---------|
|
|
69
|
-
| Single implementation | Generic trait with only one impl |
|
|
70
|
-
| Type parameter soup | `T, U, V, W` everywhere |
|
|
71
|
-
| Marker traits | Traits with no methods |
|
|
72
|
-
| Deep trait bounds | `where T: A + B + C + D + E` |
|
|
73
|
-
| Phantom generics | Type parameters not used meaningfully |
|
|
74
|
-
|
|
75
|
-
## When to Generalize
|
|
76
|
-
|
|
77
|
-
Generalize when:
|
|
78
|
-
- You have 2+ concrete types that share behavior
|
|
79
|
-
- You're writing library code for public consumption
|
|
80
|
-
- Performance requires static dispatch
|
|
81
|
-
- The abstraction simplifies the API
|
|
82
|
-
|
|
83
|
-
Don't generalize when:
|
|
84
|
-
- You "might need it later" (YAGNI)
|
|
85
|
-
- Only one type will ever implement it
|
|
86
|
-
- It makes code harder to understand
|
|
87
|
-
|
|
88
|
-
## Rule of Three
|
|
89
|
-
|
|
90
|
-
Wait until you have three similar concrete implementations before abstracting:
|
|
91
|
-
|
|
92
|
-
```rust
|
|
93
|
-
// Version 1: Just FileStorage
|
|
94
|
-
struct FileStorage { /* ... */ }
|
|
95
|
-
|
|
96
|
-
// Version 2: Added MemoryStorage, similar interface
|
|
97
|
-
struct MemoryStorage { /* ... */ }
|
|
98
|
-
|
|
99
|
-
// Version 3: Now Redis too - time to abstract
|
|
100
|
-
trait Storage {
|
|
101
|
-
fn save(&self, key: &str, value: &[u8]) -> Result<()>;
|
|
102
|
-
fn load(&self, key: &str) -> Result<Vec<u8>>;
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
## Prefer Concrete Types in Private Code
|
|
107
|
-
|
|
108
|
-
```rust
|
|
109
|
-
// Internal function - concrete type is fine
|
|
110
|
-
fn process_orders(db: &PostgresDb, orders: Vec<Order>) { }
|
|
111
|
-
|
|
112
|
-
// Public API - might benefit from abstraction
|
|
113
|
-
pub fn process_orders<S: Storage>(storage: &S, orders: Vec<Order>) { }
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
## See Also
|
|
117
|
-
|
|
118
|
-
- [type-generic-bounds](./type-generic-bounds.md) - Minimal bounds
|
|
119
|
-
- [api-sealed-trait](./api-sealed-trait.md) - Controlled extension
|
|
120
|
-
- [anti-type-erasure](./anti-type-erasure.md) - When Box<dyn> is wrong
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
# anti-panic-expected
|
|
2
|
-
|
|
3
|
-
> Don't panic on expected or recoverable errors
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Panics crash the program. They're for unrecoverable situations—bugs, corrupted state, invariant violations. Using panic for expected conditions (network failures, file not found, invalid input) makes programs fragile and forces callers to catch panics or die.
|
|
8
|
-
|
|
9
|
-
Use `Result` for recoverable errors.
|
|
10
|
-
|
|
11
|
-
## Bad
|
|
12
|
-
|
|
13
|
-
```rust
|
|
14
|
-
// Network failures are expected
|
|
15
|
-
fn fetch_data(url: &str) -> Data {
|
|
16
|
-
let response = reqwest::blocking::get(url)
|
|
17
|
-
.expect("network error"); // Crashes on timeout
|
|
18
|
-
response.json().expect("invalid json") // Crashes on bad response
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// User input is often invalid
|
|
22
|
-
fn parse_config(input: &str) -> Config {
|
|
23
|
-
toml::from_str(input).expect("invalid config") // Crashes on typo
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Files may not exist
|
|
27
|
-
fn load_settings() -> Settings {
|
|
28
|
-
let content = fs::read_to_string("settings.json")
|
|
29
|
-
.expect("settings not found"); // Crashes if missing
|
|
30
|
-
serde_json::from_str(&content).expect("invalid settings")
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Custom panic for validation
|
|
34
|
-
fn process_age(age: i32) {
|
|
35
|
-
if age < 0 {
|
|
36
|
-
panic!("age cannot be negative"); // Should return error
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Good
|
|
42
|
-
|
|
43
|
-
```rust
|
|
44
|
-
// Return errors for expected failures
|
|
45
|
-
fn fetch_data(url: &str) -> Result<Data, FetchError> {
|
|
46
|
-
let response = reqwest::blocking::get(url)
|
|
47
|
-
.context("failed to connect")?;
|
|
48
|
-
let data = response.json()
|
|
49
|
-
.context("failed to parse response")?;
|
|
50
|
-
Ok(data)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Validate and return Result
|
|
54
|
-
fn parse_config(input: &str) -> Result<Config, ConfigError> {
|
|
55
|
-
toml::from_str(input).map_err(ConfigError::Parse)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Handle missing files gracefully
|
|
59
|
-
fn load_settings() -> Result<Settings, SettingsError> {
|
|
60
|
-
let content = fs::read_to_string("settings.json")?;
|
|
61
|
-
let settings = serde_json::from_str(&content)?;
|
|
62
|
-
Ok(settings)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Return error for validation failure
|
|
66
|
-
fn process_age(age: i32) -> Result<(), ValidationError> {
|
|
67
|
-
if age < 0 {
|
|
68
|
-
return Err(ValidationError::NegativeAge);
|
|
69
|
-
}
|
|
70
|
-
Ok(())
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## When to Panic
|
|
75
|
-
|
|
76
|
-
Panic IS appropriate for:
|
|
77
|
-
|
|
78
|
-
```rust
|
|
79
|
-
// Bug detection - invariant violated
|
|
80
|
-
fn get_unchecked(&self, index: usize) -> &T {
|
|
81
|
-
assert!(index < self.len(), "index out of bounds - this is a bug");
|
|
82
|
-
unsafe { self.data.get_unchecked(index) }
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Unrecoverable state
|
|
86
|
-
fn init() {
|
|
87
|
-
if !CAN_PROCEED {
|
|
88
|
-
panic!("system requirements not met");
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Tests
|
|
93
|
-
#[test]
|
|
94
|
-
fn test_fails() {
|
|
95
|
-
panic!("expected panic in test");
|
|
96
|
-
}
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## Decision Guide
|
|
100
|
-
|
|
101
|
-
| Condition | Action |
|
|
102
|
-
|-----------|--------|
|
|
103
|
-
| Invalid user input | Return `Err` |
|
|
104
|
-
| Network failure | Return `Err` |
|
|
105
|
-
| File not found | Return `Err` |
|
|
106
|
-
| Malformed data | Return `Err` |
|
|
107
|
-
| Bug/impossible state | `panic!` or `unreachable!` |
|
|
108
|
-
| Failed assertion in test | `panic!` |
|
|
109
|
-
| Unrecoverable init failure | `panic!` |
|
|
110
|
-
|
|
111
|
-
## Anti-pattern: panic! for Control Flow
|
|
112
|
-
|
|
113
|
-
```rust
|
|
114
|
-
// BAD: Using panic for control flow
|
|
115
|
-
fn find_or_die(items: &[Item], id: u64) -> &Item {
|
|
116
|
-
items.iter()
|
|
117
|
-
.find(|i| i.id == id)
|
|
118
|
-
.unwrap_or_else(|| panic!("item {} not found", id))
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// GOOD: Return Option or Result
|
|
122
|
-
fn find(items: &[Item], id: u64) -> Option<&Item> {
|
|
123
|
-
items.iter().find(|i| i.id == id)
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
## See Also
|
|
128
|
-
|
|
129
|
-
- [err-result-over-panic](./err-result-over-panic.md) - Use Result
|
|
130
|
-
- [anti-unwrap-abuse](./anti-unwrap-abuse.md) - Unwrap anti-pattern
|
|
131
|
-
- [err-expect-bugs-only](./err-expect-bugs-only.md) - When to expect
|
package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
# anti-premature-optimize
|
|
2
|
-
|
|
3
|
-
> Don't optimize before profiling
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Premature optimization wastes time, complicates code, and often targets the wrong bottlenecks. Most code isn't performance-critical; the hot 10% matters. Profile first, then optimize the actual bottlenecks with data-driven decisions.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// "Optimizing" without measurement
|
|
13
|
-
fn sum(data: &[i32]) -> i32 {
|
|
14
|
-
// Using unsafe "for performance" without profiling
|
|
15
|
-
unsafe {
|
|
16
|
-
let mut sum = 0;
|
|
17
|
-
for i in 0..data.len() {
|
|
18
|
-
sum += *data.get_unchecked(i);
|
|
19
|
-
}
|
|
20
|
-
sum
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Complex caching with no evidence it's needed
|
|
25
|
-
lazy_static! {
|
|
26
|
-
static ref CACHE: RwLock<HashMap<String, Arc<Result>>> =
|
|
27
|
-
RwLock::new(HashMap::new());
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Hand-rolled data structures "for speed"
|
|
31
|
-
struct MyVec<T> {
|
|
32
|
-
ptr: *mut T,
|
|
33
|
-
len: usize,
|
|
34
|
-
cap: usize,
|
|
35
|
-
}
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Good
|
|
39
|
-
|
|
40
|
-
```rust
|
|
41
|
-
// Simple, idiomatic - let compiler optimize
|
|
42
|
-
fn sum(data: &[i32]) -> i32 {
|
|
43
|
-
data.iter().sum()
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Profile, then optimize if needed
|
|
47
|
-
fn sum_optimized(data: &[i32]) -> i32 {
|
|
48
|
-
// After profiling showed this is a bottleneck,
|
|
49
|
-
// we measured that manual SIMD gives 3x speedup
|
|
50
|
-
#[cfg(target_arch = "x86_64")]
|
|
51
|
-
{
|
|
52
|
-
// SIMD implementation with benchmark data
|
|
53
|
-
}
|
|
54
|
-
#[cfg(not(target_arch = "x86_64"))]
|
|
55
|
-
{
|
|
56
|
-
data.iter().sum()
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Use standard library - it's well-optimized
|
|
61
|
-
let cache: HashMap<String, Result> = HashMap::new();
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Profiling Workflow
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
# 1. Write correct code first
|
|
68
|
-
cargo build --release
|
|
69
|
-
|
|
70
|
-
# 2. Profile with real workloads
|
|
71
|
-
cargo flamegraph --bin my_app -- --real-args
|
|
72
|
-
# or
|
|
73
|
-
cargo bench
|
|
74
|
-
|
|
75
|
-
# 3. Identify hotspots (top 10% of time)
|
|
76
|
-
|
|
77
|
-
# 4. Measure before optimizing
|
|
78
|
-
# 5. Optimize ONE thing
|
|
79
|
-
# 6. Measure after - verify improvement
|
|
80
|
-
# 7. Repeat if still slow
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## Optimization Principles
|
|
84
|
-
|
|
85
|
-
| Do | Don't |
|
|
86
|
-
|----|-------|
|
|
87
|
-
| Profile first | Guess at bottlenecks |
|
|
88
|
-
| Optimize hotspots | Optimize everything |
|
|
89
|
-
| Measure improvement | Assume it's faster |
|
|
90
|
-
| Keep it simple | Add complexity speculatively |
|
|
91
|
-
| Trust the compiler | Outsmart the compiler |
|
|
92
|
-
|
|
93
|
-
## When to Optimize
|
|
94
|
-
|
|
95
|
-
```rust
|
|
96
|
-
// AFTER profiling shows this is 40% of runtime
|
|
97
|
-
#[inline]
|
|
98
|
-
fn hot_function(data: &[u8]) -> u64 {
|
|
99
|
-
// Optimized implementation justified by benchmarks
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Clear, measurable benefit documented
|
|
103
|
-
/// Pre-allocated buffer for repeated formatting.
|
|
104
|
-
/// Benchmarks show 3x speedup for >1000 calls/sec workloads.
|
|
105
|
-
struct FormatterPool {
|
|
106
|
-
buffers: Vec<String>,
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## Common Premature Optimizations
|
|
111
|
-
|
|
112
|
-
| Premature | Reality |
|
|
113
|
-
|-----------|---------|
|
|
114
|
-
| `#[inline(always)]` everywhere | Compiler usually knows better |
|
|
115
|
-
| `unsafe` for bounds check removal | Iterator does this safely |
|
|
116
|
-
| Custom allocator | Default is usually fine |
|
|
117
|
-
| Object pooling | Allocator is fast enough |
|
|
118
|
-
| Manual SIMD | Auto-vectorization works |
|
|
119
|
-
|
|
120
|
-
## Profile Tools
|
|
121
|
-
|
|
122
|
-
```bash
|
|
123
|
-
# Sampling profiler
|
|
124
|
-
perf record ./target/release/app && perf report
|
|
125
|
-
|
|
126
|
-
# Flamegraph
|
|
127
|
-
cargo install flamegraph
|
|
128
|
-
cargo flamegraph
|
|
129
|
-
|
|
130
|
-
# Criterion benchmarks
|
|
131
|
-
cargo bench
|
|
132
|
-
|
|
133
|
-
# Memory profiling
|
|
134
|
-
valgrind --tool=massif ./target/release/app
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
## Document Optimizations
|
|
138
|
-
|
|
139
|
-
```rust
|
|
140
|
-
/// Lookup table for fast character classification.
|
|
141
|
-
///
|
|
142
|
-
/// # Performance
|
|
143
|
-
///
|
|
144
|
-
/// Benchmarked with criterion (benchmarks/char_class.rs):
|
|
145
|
-
/// - Table lookup: 2.3ns/op
|
|
146
|
-
/// - Match statement: 8.7ns/op
|
|
147
|
-
///
|
|
148
|
-
/// Justified for hot path in parser (called 10M+ times).
|
|
149
|
-
static CHAR_CLASS: [CharClass; 256] = [/* ... */];
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
## See Also
|
|
153
|
-
|
|
154
|
-
- [perf-profile-first](./perf-profile-first.md) - Profile before optimize
|
|
155
|
-
- [test-criterion-bench](./test-criterion-bench.md) - Benchmarking
|
|
156
|
-
- [opt-inline-small](./opt-inline-small.md) - Inline guidelines
|