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,187 +0,0 @@
|
|
|
1
|
-
# opt-cache-friendly
|
|
2
|
-
|
|
3
|
-
> Organize data for cache-efficient access patterns
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Cache misses are expensive—a L3 cache miss costs ~100+ cycles vs ~4 cycles for L1 hit. Data layout and access patterns determine cache efficiency. Arrays of structs (AoS) vs structs of arrays (SoA), memory locality, and access patterns can make order-of-magnitude performance differences.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// Array of Structs (AoS) - poor cache use when accessing one field
|
|
13
|
-
struct Particle {
|
|
14
|
-
position: [f32; 3], // 12 bytes
|
|
15
|
-
velocity: [f32; 3], // 12 bytes
|
|
16
|
-
mass: f32, // 4 bytes
|
|
17
|
-
id: u64, // 8 bytes
|
|
18
|
-
flags: u8, // 1 byte + padding
|
|
19
|
-
// Total: 40 bytes per particle
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
fn update_positions(particles: &mut [Particle], dt: f32) {
|
|
23
|
-
for p in particles {
|
|
24
|
-
// Access position and velocity - 24 bytes
|
|
25
|
-
// But loads 40-byte struct per particle
|
|
26
|
-
// 16 bytes wasted per cache line load
|
|
27
|
-
p.position[0] += p.velocity[0] * dt;
|
|
28
|
-
p.position[1] += p.velocity[1] * dt;
|
|
29
|
-
p.position[2] += p.velocity[2] * dt;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Good
|
|
35
|
-
|
|
36
|
-
```rust
|
|
37
|
-
// Struct of Arrays (SoA) - cache-efficient for field access
|
|
38
|
-
struct Particles {
|
|
39
|
-
positions_x: Vec<f32>,
|
|
40
|
-
positions_y: Vec<f32>,
|
|
41
|
-
positions_z: Vec<f32>,
|
|
42
|
-
velocities_x: Vec<f32>,
|
|
43
|
-
velocities_y: Vec<f32>,
|
|
44
|
-
velocities_z: Vec<f32>,
|
|
45
|
-
masses: Vec<f32>,
|
|
46
|
-
ids: Vec<u64>,
|
|
47
|
-
flags: Vec<u8>,
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
fn update_positions(p: &mut Particles, dt: f32) {
|
|
51
|
-
// Access contiguous memory - perfect cache utilization
|
|
52
|
-
for (px, vx) in p.positions_x.iter_mut().zip(&p.velocities_x) {
|
|
53
|
-
*px += vx * dt;
|
|
54
|
-
}
|
|
55
|
-
for (py, vy) in p.positions_y.iter_mut().zip(&p.velocities_y) {
|
|
56
|
-
*py += vy * dt;
|
|
57
|
-
}
|
|
58
|
-
for (pz, vz) in p.positions_z.iter_mut().zip(&p.velocities_z) {
|
|
59
|
-
*pz += vz * dt;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Hot/Cold Splitting
|
|
65
|
-
|
|
66
|
-
```rust
|
|
67
|
-
// Separate frequently and rarely accessed fields
|
|
68
|
-
struct EntityHot {
|
|
69
|
-
position: [f32; 3],
|
|
70
|
-
velocity: [f32; 3],
|
|
71
|
-
// Hot data - accessed every frame
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
struct EntityCold {
|
|
75
|
-
name: String,
|
|
76
|
-
creation_time: Instant,
|
|
77
|
-
metadata: HashMap<String, Value>,
|
|
78
|
-
// Cold data - rarely accessed
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
struct Entities {
|
|
82
|
-
hot: Vec<EntityHot>,
|
|
83
|
-
cold: Vec<EntityCold>,
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Hot loop touches only hot data
|
|
87
|
-
fn update(entities: &mut Entities, dt: f32) {
|
|
88
|
-
for e in &mut entities.hot {
|
|
89
|
-
e.position[0] += e.velocity[0] * dt;
|
|
90
|
-
// Cold data stays out of cache
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## Prefetching
|
|
96
|
-
|
|
97
|
-
```rust
|
|
98
|
-
// Process in cache-line-sized chunks
|
|
99
|
-
const CACHE_LINE: usize = 64;
|
|
100
|
-
|
|
101
|
-
fn process_with_prefetch(data: &mut [u8]) {
|
|
102
|
-
for chunk in data.chunks_mut(CACHE_LINE) {
|
|
103
|
-
// Prefetch next chunk while processing current
|
|
104
|
-
// (automatic in many cases, manual for complex patterns)
|
|
105
|
-
process_chunk(chunk);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Matrix multiplication - block for cache
|
|
110
|
-
fn matmul_blocked(a: &[f64], b: &[f64], c: &mut [f64], n: usize) {
|
|
111
|
-
const BLOCK: usize = 32; // Fits in L1 cache
|
|
112
|
-
|
|
113
|
-
for i0 in (0..n).step_by(BLOCK) {
|
|
114
|
-
for j0 in (0..n).step_by(BLOCK) {
|
|
115
|
-
for k0 in (0..n).step_by(BLOCK) {
|
|
116
|
-
// Process BLOCK x BLOCK tile
|
|
117
|
-
for i in i0..min(i0 + BLOCK, n) {
|
|
118
|
-
for j in j0..min(j0 + BLOCK, n) {
|
|
119
|
-
// Inner loop operates on cached data
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## Avoid Pointer Chasing
|
|
129
|
-
|
|
130
|
-
```rust
|
|
131
|
-
// Bad: linked list - random memory access
|
|
132
|
-
struct Node {
|
|
133
|
-
value: i32,
|
|
134
|
-
next: Option<Box<Node>>,
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
fn sum_linked(head: &Node) -> i32 {
|
|
138
|
-
// Each node is a cache miss
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Good: contiguous vector
|
|
142
|
-
fn sum_vector(data: &[i32]) -> i32 {
|
|
143
|
-
data.iter().sum() // Sequential access, prefetcher happy
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Good: if graph needed, use indices
|
|
147
|
-
struct Graph {
|
|
148
|
-
values: Vec<i32>,
|
|
149
|
-
edges: Vec<usize>, // Indices into values
|
|
150
|
-
}
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
## Memory Layout Attributes
|
|
154
|
-
|
|
155
|
-
```rust
|
|
156
|
-
// Ensure cache-line alignment
|
|
157
|
-
#[repr(C, align(64))]
|
|
158
|
-
struct CacheAligned {
|
|
159
|
-
data: [u8; 64],
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Prevent false sharing in concurrent code
|
|
163
|
-
#[repr(C, align(64))]
|
|
164
|
-
struct PaddedCounter {
|
|
165
|
-
value: AtomicU64,
|
|
166
|
-
_pad: [u8; 56],
|
|
167
|
-
}
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
## Measuring Cache Performance
|
|
171
|
-
|
|
172
|
-
```bash
|
|
173
|
-
# Linux perf
|
|
174
|
-
perf stat -e cache-references,cache-misses ./my_program
|
|
175
|
-
|
|
176
|
-
# Detailed cache analysis
|
|
177
|
-
perf stat -e L1-dcache-loads,L1-dcache-load-misses,LLC-loads,LLC-load-misses ./my_program
|
|
178
|
-
|
|
179
|
-
# Cachegrind
|
|
180
|
-
valgrind --tool=cachegrind ./my_program
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
## See Also
|
|
184
|
-
|
|
185
|
-
- [mem-smaller-integers](./mem-smaller-integers.md) - Smaller data fits more in cache
|
|
186
|
-
- [mem-box-large-variant](./mem-box-large-variant.md) - Keep enum sizes small
|
|
187
|
-
- [opt-bounds-check](./opt-bounds-check.md) - Sequential access patterns
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
# opt-codegen-units
|
|
2
|
-
|
|
3
|
-
> Set `codegen-units = 1` for maximum optimization in release builds
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
By default, Cargo splits code into multiple codegen units for parallel compilation. This speeds up builds but prevents some cross-unit optimizations. Setting `codegen-units = 1` allows LLVM to optimize across the entire crate, potentially improving runtime performance by 5-20% at the cost of slower builds.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```toml
|
|
12
|
-
# Cargo.toml - default settings
|
|
13
|
-
[profile.release]
|
|
14
|
-
# codegen-units defaults to 16
|
|
15
|
-
# Fast to compile, but misses optimization opportunities
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Good
|
|
19
|
-
|
|
20
|
-
```toml
|
|
21
|
-
# Cargo.toml - optimized for runtime performance
|
|
22
|
-
[profile.release]
|
|
23
|
-
codegen-units = 1 # Single unit = better optimization
|
|
24
|
-
lto = true # Link-time optimization
|
|
25
|
-
opt-level = 3 # Maximum optimization
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## What codegen-units Affects
|
|
29
|
-
|
|
30
|
-
| Codegen Units | Compile Time | Runtime Performance | Memory Use |
|
|
31
|
-
|---------------|--------------|---------------------|------------|
|
|
32
|
-
| 16 (default) | Faster | Baseline | Lower |
|
|
33
|
-
| 4-8 | Moderate | Slightly better | Moderate |
|
|
34
|
-
| 1 | Slower | Best | Higher |
|
|
35
|
-
|
|
36
|
-
## How It Works
|
|
37
|
-
|
|
38
|
-
```rust
|
|
39
|
-
// With codegen-units = 16:
|
|
40
|
-
// - Crate split into 16 independent compilation units
|
|
41
|
-
// - Compiled in parallel
|
|
42
|
-
// - Limited visibility between units for optimization
|
|
43
|
-
|
|
44
|
-
// With codegen-units = 1:
|
|
45
|
-
// - Entire crate in single unit
|
|
46
|
-
// - LLVM sees all code at once
|
|
47
|
-
// - Can inline across module boundaries
|
|
48
|
-
// - Better dead code elimination
|
|
49
|
-
// - Better constant propagation
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Full Release Profile
|
|
53
|
-
|
|
54
|
-
```toml
|
|
55
|
-
[profile.release]
|
|
56
|
-
# Maximum runtime performance
|
|
57
|
-
opt-level = 3
|
|
58
|
-
lto = "fat"
|
|
59
|
-
codegen-units = 1
|
|
60
|
-
panic = "abort" # Smaller binary, slight perf gain
|
|
61
|
-
strip = true # Smaller binary
|
|
62
|
-
|
|
63
|
-
[profile.release-with-debug]
|
|
64
|
-
# Performance with debugging ability
|
|
65
|
-
inherits = "release"
|
|
66
|
-
debug = true # Keep debug symbols
|
|
67
|
-
strip = false
|
|
68
|
-
|
|
69
|
-
[profile.bench]
|
|
70
|
-
# For benchmarking
|
|
71
|
-
inherits = "release"
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Build Time Trade-offs
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
# Default release build (fast compile)
|
|
78
|
-
cargo build --release
|
|
79
|
-
# Time: ~30s
|
|
80
|
-
|
|
81
|
-
# Optimized release build (slow compile, fast runtime)
|
|
82
|
-
# With codegen-units = 1, lto = "fat"
|
|
83
|
-
cargo build --release
|
|
84
|
-
# Time: ~2-5min, but potentially 10-20% faster binary
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
## Per-Profile Configuration
|
|
88
|
-
|
|
89
|
-
```toml
|
|
90
|
-
# Fast debug builds
|
|
91
|
-
[profile.dev]
|
|
92
|
-
codegen-units = 256 # Maximum parallelism
|
|
93
|
-
|
|
94
|
-
# Fast CI builds
|
|
95
|
-
[profile.ci]
|
|
96
|
-
inherits = "release"
|
|
97
|
-
codegen-units = 16 # Balance compile time vs runtime
|
|
98
|
-
lto = "thin" # Faster than "fat"
|
|
99
|
-
|
|
100
|
-
# Production release
|
|
101
|
-
[profile.production]
|
|
102
|
-
inherits = "release"
|
|
103
|
-
codegen-units = 1
|
|
104
|
-
lto = "fat"
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
## When to Use What
|
|
108
|
-
|
|
109
|
-
```rust
|
|
110
|
-
// codegen-units = 16 (default)
|
|
111
|
-
// - Development builds
|
|
112
|
-
// - CI where compile time matters
|
|
113
|
-
// - When runtime performance isn't critical
|
|
114
|
-
|
|
115
|
-
// codegen-units = 1
|
|
116
|
-
// - Production deployments
|
|
117
|
-
// - Performance-critical applications
|
|
118
|
-
// - Final releases
|
|
119
|
-
// - Benchmarking
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## Measuring Impact
|
|
123
|
-
|
|
124
|
-
```bash
|
|
125
|
-
# Build with different settings
|
|
126
|
-
cargo build --release
|
|
127
|
-
|
|
128
|
-
# Benchmark
|
|
129
|
-
cargo bench
|
|
130
|
-
|
|
131
|
-
# Compare binary sizes
|
|
132
|
-
ls -lh target/release/my_binary
|
|
133
|
-
|
|
134
|
-
# Profile runtime
|
|
135
|
-
perf stat ./target/release/my_binary
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## See Also
|
|
139
|
-
|
|
140
|
-
- [opt-lto-release](./opt-lto-release.md) - Link-time optimization
|
|
141
|
-
- [opt-pgo-profile](./opt-pgo-profile.md) - Profile-guided optimization
|
|
142
|
-
- [opt-target-cpu](./opt-target-cpu.md) - CPU-specific optimization
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
# opt-cold-unlikely
|
|
2
|
-
|
|
3
|
-
> Mark unlikely code paths with `#[cold]` to help compiler optimization
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
The `#[cold]` attribute tells the compiler that a function is rarely called. The compiler uses this to optimize code layout—keeping cold code away from hot code improves instruction cache utilization. Combined with branch layout optimization, this can measurably improve performance.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// All branches treated equally
|
|
13
|
-
fn validate(input: &str) -> Result<Data, ValidationError> {
|
|
14
|
-
if input.is_empty() {
|
|
15
|
-
return Err(ValidationError::Empty); // Rare
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if input.len() > 1000 {
|
|
19
|
-
return Err(ValidationError::TooLong); // Rare
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if !input.is_ascii() {
|
|
23
|
-
return Err(ValidationError::NonAscii); // Rare
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// This is the common case
|
|
27
|
-
Ok(parse_data(input))
|
|
28
|
-
}
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Good
|
|
32
|
-
|
|
33
|
-
```rust
|
|
34
|
-
fn validate(input: &str) -> Result<Data, ValidationError> {
|
|
35
|
-
if input.is_empty() {
|
|
36
|
-
return cold_empty_error();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if input.len() > 1000 {
|
|
40
|
-
return cold_too_long_error();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if !input.is_ascii() {
|
|
44
|
-
return cold_non_ascii_error();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
Ok(parse_data(input))
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
#[cold]
|
|
51
|
-
fn cold_empty_error() -> Result<Data, ValidationError> {
|
|
52
|
-
Err(ValidationError::Empty)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
#[cold]
|
|
56
|
-
fn cold_too_long_error() -> Result<Data, ValidationError> {
|
|
57
|
-
Err(ValidationError::TooLong)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
#[cold]
|
|
61
|
-
fn cold_non_ascii_error() -> Result<Data, ValidationError> {
|
|
62
|
-
Err(ValidationError::NonAscii)
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
## What #[cold] Does
|
|
67
|
-
|
|
68
|
-
1. **Code placement**: Cold functions are placed in separate code sections, away from hot code
|
|
69
|
-
2. **Branch prediction**: Compiler generates branch hints favoring the non-cold path
|
|
70
|
-
3. **Inlining decisions**: Cold functions are not inlined into hot paths
|
|
71
|
-
4. **Optimization budget**: Compiler spends less effort optimizing cold code
|
|
72
|
-
|
|
73
|
-
## Common Cold Patterns
|
|
74
|
-
|
|
75
|
-
```rust
|
|
76
|
-
// Error handling
|
|
77
|
-
#[cold]
|
|
78
|
-
fn handle_error<E: std::fmt::Display>(e: E) -> ! {
|
|
79
|
-
eprintln!("Fatal error: {}", e);
|
|
80
|
-
std::process::exit(1);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Logging rare events
|
|
84
|
-
#[cold]
|
|
85
|
-
fn log_rare_event(event: &Event) {
|
|
86
|
-
log::warn!("Rare event occurred: {:?}", event);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Fallback paths
|
|
90
|
-
#[cold]
|
|
91
|
-
fn slow_fallback(data: &Data) -> Output {
|
|
92
|
-
// This path should rarely be taken
|
|
93
|
-
compute_slowly(data)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Panic handlers
|
|
97
|
-
#[cold]
|
|
98
|
-
fn panic_invalid_state(state: &State) -> ! {
|
|
99
|
-
panic!("Invalid state: {:?}", state);
|
|
100
|
-
}
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
## Assertions and Invariants
|
|
104
|
-
|
|
105
|
-
```rust
|
|
106
|
-
fn get_unchecked(&self, index: usize) -> &T {
|
|
107
|
-
if index >= self.len {
|
|
108
|
-
cold_bounds_panic(index, self.len);
|
|
109
|
-
}
|
|
110
|
-
unsafe { &*self.ptr.add(index) }
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
#[cold]
|
|
114
|
-
#[inline(never)]
|
|
115
|
-
fn cold_bounds_panic(index: usize, len: usize) -> ! {
|
|
116
|
-
panic!("index out of bounds: the len is {} but the index is {}", len, index);
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## Combining with #[inline(never)]
|
|
121
|
-
|
|
122
|
-
```rust
|
|
123
|
-
// Usually combine both for maximum effect
|
|
124
|
-
#[cold]
|
|
125
|
-
#[inline(never)]
|
|
126
|
-
fn error_path() -> Error {
|
|
127
|
-
// Complex error construction stays out of hot code
|
|
128
|
-
Error {
|
|
129
|
-
backtrace: Backtrace::capture(),
|
|
130
|
-
context: gather_context(),
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
## Measuring Impact
|
|
136
|
-
|
|
137
|
-
```rust
|
|
138
|
-
// Check code layout with objdump
|
|
139
|
-
// objdump -d target/release/binary | less
|
|
140
|
-
|
|
141
|
-
// Look for .cold sections
|
|
142
|
-
// nm target/release/binary | grep cold
|
|
143
|
-
|
|
144
|
-
// Profile to verify improvement
|
|
145
|
-
// perf stat -e cache-misses,cache-references ./binary
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
## See Also
|
|
149
|
-
|
|
150
|
-
- [opt-inline-never-cold](./opt-inline-never-cold.md) - Combining with inline(never)
|
|
151
|
-
- [opt-likely-hint](./opt-likely-hint.md) - Branch prediction hints
|
|
152
|
-
- [err-result-over-panic](./err-result-over-panic.md) - Error handling
|
package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
# opt-inline-always-rare
|
|
2
|
-
|
|
3
|
-
> Use `#[inline(always)]` sparingly—only for critical hot paths proven by profiling
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
`#[inline(always)]` forces the compiler to inline a function regardless of heuristics. Overuse increases binary size, hurts instruction cache, and can slow down code. The compiler is usually smarter about inlining than humans. Reserve this for measured hot paths where benchmarks prove a benefit.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// Annotating everything - trusting intuition over data
|
|
13
|
-
#[inline(always)]
|
|
14
|
-
pub fn get_name(&self) -> &str {
|
|
15
|
-
&self.name
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
#[inline(always)]
|
|
19
|
-
pub fn calculate_tax(amount: f64) -> f64 {
|
|
20
|
-
amount * 0.1
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
#[inline(always)]
|
|
24
|
-
fn helper(x: i32) -> i32 {
|
|
25
|
-
x + 1
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Result: bloated binary, poor cache utilization
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Good
|
|
32
|
-
|
|
33
|
-
```rust
|
|
34
|
-
// Let compiler decide for most functions
|
|
35
|
-
pub fn get_name(&self) -> &str {
|
|
36
|
-
&self.name
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
pub fn calculate_tax(amount: f64) -> f64 {
|
|
40
|
-
amount * 0.1
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Only force inline for proven hot paths
|
|
44
|
-
impl Hasher for MyHasher {
|
|
45
|
-
// Hasher::write is called millions of times in tight loops
|
|
46
|
-
// Profiling showed 15% improvement from forced inlining
|
|
47
|
-
#[inline(always)]
|
|
48
|
-
fn write(&mut self, bytes: &[u8]) {
|
|
49
|
-
// Very small, very hot
|
|
50
|
-
self.state = self.state.wrapping_add(bytes.len() as u64);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## When #[inline(always)] Helps
|
|
56
|
-
|
|
57
|
-
```rust
|
|
58
|
-
// ✅ Tiny functions in hot inner loops
|
|
59
|
-
#[inline(always)]
|
|
60
|
-
fn fast_hash(a: u64, b: u64) -> u64 {
|
|
61
|
-
a.wrapping_mul(b).wrapping_add(a)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// ✅ Generic functions that benefit from monomorphization
|
|
65
|
-
#[inline(always)]
|
|
66
|
-
fn swap<T>(a: &mut T, b: &mut T) {
|
|
67
|
-
std::mem::swap(a, b);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// ✅ Iterator adapters and closures
|
|
71
|
-
#[inline(always)]
|
|
72
|
-
fn apply<T, F: Fn(T) -> T>(f: F, x: T) -> T {
|
|
73
|
-
f(x)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// ✅ SIMD/vectorization helpers
|
|
77
|
-
#[inline(always)]
|
|
78
|
-
fn add_simd(a: &[f32], b: &[f32], out: &mut [f32]) {
|
|
79
|
-
// ...
|
|
80
|
-
}
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## Inline Variants
|
|
84
|
-
|
|
85
|
-
```rust
|
|
86
|
-
// #[inline] - hint to inline, compiler may ignore
|
|
87
|
-
#[inline]
|
|
88
|
-
fn suggested_inline(x: i32) -> i32 { x + 1 }
|
|
89
|
-
|
|
90
|
-
// #[inline(always)] - force inline (almost always)
|
|
91
|
-
#[inline(always)]
|
|
92
|
-
fn force_inline(x: i32) -> i32 { x + 1 }
|
|
93
|
-
|
|
94
|
-
// #[inline(never)] - prevent inlining (for profiling, code size)
|
|
95
|
-
#[inline(never)]
|
|
96
|
-
fn no_inline(x: i32) -> i32 { x + 1 }
|
|
97
|
-
|
|
98
|
-
// No annotation - compiler decides based on heuristics
|
|
99
|
-
fn compiler_decides(x: i32) -> i32 { x + 1 }
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Measuring Inline Impact
|
|
103
|
-
|
|
104
|
-
```rust
|
|
105
|
-
// Use criterion to benchmark
|
|
106
|
-
use criterion::{criterion_group, criterion_main, Criterion};
|
|
107
|
-
|
|
108
|
-
fn bench_with_inline(c: &mut Criterion) {
|
|
109
|
-
c.bench_function("hot_path_inline", |b| {
|
|
110
|
-
b.iter(|| hot_loop())
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Compare binary sizes
|
|
115
|
-
// cargo bloat --release --crates
|
|
116
|
-
|
|
117
|
-
// Check if function was inlined
|
|
118
|
-
// cargo asm --rust my_crate::hot_function
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
## Generic Functions
|
|
122
|
-
|
|
123
|
-
```rust
|
|
124
|
-
// Generic functions across crate boundaries often need #[inline]
|
|
125
|
-
// Because the generic code is compiled in the calling crate
|
|
126
|
-
|
|
127
|
-
// In library crate:
|
|
128
|
-
#[inline] // Allow inlining in downstream crates
|
|
129
|
-
pub fn generic_function<T: Display>(x: T) {
|
|
130
|
-
println!("{}", x);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Without #[inline], the generic function can't be inlined
|
|
134
|
-
// across crate boundaries even if beneficial
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
## See Also
|
|
138
|
-
|
|
139
|
-
- [opt-inline-small](./opt-inline-small.md) - Regular inline for small functions
|
|
140
|
-
- [opt-inline-never-cold](./opt-inline-never-cold.md) - Preventing inlining
|
|
141
|
-
- [perf-profile-first](./perf-profile-first.md) - Profile before optimizing
|