agy-superpowers 5.2.2 → 5.2.4
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/CLAUDE.md +80 -0
- package/template/agent/rules/code-styles.md +31 -32
- package/template/agent/rules/debug-confirmation-policy.md +2 -0
- package/template/agent/rules/file-length-policy.md +2 -0
- package/template/agent/rules/git-policy.md +7 -0
- package/template/agent/rules/language-matching.md +2 -0
- package/template/agent/rules/scratch-scripts.md +39 -0
- package/template/agent/rules/superpowers.md +8 -51
- package/template/agent/skills/executing-plans/SKILL.md +17 -0
- package/template/agent/skills/systematic-debugging/SKILL.md +16 -0
- package/template/agent/skills/test-driven-development/SKILL.md +16 -0
- package/template/agent/skills/verification-before-completion/SKILL.md +22 -0
- package/template/agent/skills/writing-plans/SKILL.md +16 -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,174 +0,0 @@
|
|
|
1
|
-
# mem-reuse-collections
|
|
2
|
-
|
|
3
|
-
> Clear and reuse collections instead of creating new ones in loops
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Creating new `Vec`, `String`, or `HashMap` instances in hot loops generates significant allocator pressure. Clearing a collection and reusing it keeps the existing capacity, avoiding repeated allocation/deallocation cycles. This is especially impactful for frequently-executed code paths.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
fn process_batches(batches: &[Batch]) -> Vec<Result> {
|
|
13
|
-
let mut results = Vec::new();
|
|
14
|
-
|
|
15
|
-
for batch in batches {
|
|
16
|
-
let mut temp = Vec::new(); // Allocates every iteration
|
|
17
|
-
|
|
18
|
-
for item in &batch.items {
|
|
19
|
-
temp.push(transform(item));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
results.push(aggregate(&temp));
|
|
23
|
-
// temp dropped here, deallocation
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
results
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
fn format_lines(items: &[Item]) -> String {
|
|
30
|
-
let mut output = String::new();
|
|
31
|
-
|
|
32
|
-
for item in items {
|
|
33
|
-
let line = format!("{}: {}", item.name, item.value); // Allocates
|
|
34
|
-
output.push_str(&line);
|
|
35
|
-
output.push('\n');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
output
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Good
|
|
43
|
-
|
|
44
|
-
```rust
|
|
45
|
-
fn process_batches(batches: &[Batch]) -> Vec<Result> {
|
|
46
|
-
let mut results = Vec::with_capacity(batches.len());
|
|
47
|
-
let mut temp = Vec::new(); // Allocate once outside loop
|
|
48
|
-
|
|
49
|
-
for batch in batches {
|
|
50
|
-
temp.clear(); // Reuse allocation, just reset length
|
|
51
|
-
|
|
52
|
-
for item in &batch.items {
|
|
53
|
-
temp.push(transform(item));
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
results.push(aggregate(&temp));
|
|
57
|
-
// temp keeps its capacity for next iteration
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
results
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
fn format_lines(items: &[Item]) -> String {
|
|
64
|
-
use std::fmt::Write;
|
|
65
|
-
|
|
66
|
-
let mut output = String::new();
|
|
67
|
-
let mut line = String::new(); // Reusable buffer
|
|
68
|
-
|
|
69
|
-
for item in items {
|
|
70
|
-
line.clear();
|
|
71
|
-
write!(&mut line, "{}: {}", item.name, item.value).unwrap();
|
|
72
|
-
output.push_str(&line);
|
|
73
|
-
output.push('\n');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
output
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## Clear vs Drain vs New
|
|
81
|
-
|
|
82
|
-
```rust
|
|
83
|
-
let mut vec = vec![1, 2, 3, 4, 5];
|
|
84
|
-
|
|
85
|
-
// clear(): keeps capacity, O(n) for Drop types
|
|
86
|
-
vec.clear();
|
|
87
|
-
assert_eq!(vec.len(), 0);
|
|
88
|
-
assert!(vec.capacity() >= 5);
|
|
89
|
-
|
|
90
|
-
// drain(): returns iterator, clears after iteration
|
|
91
|
-
let drained: Vec<_> = vec.drain(..).collect();
|
|
92
|
-
|
|
93
|
-
// truncate(): keeps first n elements
|
|
94
|
-
vec.truncate(2);
|
|
95
|
-
|
|
96
|
-
// Creating new: loses all capacity
|
|
97
|
-
vec = Vec::new(); // Capacity gone
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## HashMap Reuse
|
|
101
|
-
|
|
102
|
-
```rust
|
|
103
|
-
use std::collections::HashMap;
|
|
104
|
-
|
|
105
|
-
fn count_words_per_line(lines: &[&str]) -> Vec<HashMap<String, usize>> {
|
|
106
|
-
let mut results = Vec::with_capacity(lines.len());
|
|
107
|
-
let mut counts = HashMap::new(); // Reuse across iterations
|
|
108
|
-
|
|
109
|
-
for line in lines {
|
|
110
|
-
counts.clear(); // Keeps bucket allocation
|
|
111
|
-
|
|
112
|
-
for word in line.split_whitespace() {
|
|
113
|
-
*counts.entry(word.to_string()).or_insert(0) += 1;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
results.push(counts.clone());
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
results
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
## BufWriter Pattern
|
|
124
|
-
|
|
125
|
-
```rust
|
|
126
|
-
use std::io::{BufWriter, Write};
|
|
127
|
-
|
|
128
|
-
fn write_many_records(records: &[Record], mut output: impl Write) -> std::io::Result<()> {
|
|
129
|
-
// BufWriter reuses its internal buffer
|
|
130
|
-
let mut writer = BufWriter::with_capacity(8192, &mut output);
|
|
131
|
-
let mut line = String::with_capacity(256); // Reusable formatting buffer
|
|
132
|
-
|
|
133
|
-
for record in records {
|
|
134
|
-
line.clear();
|
|
135
|
-
format_record(record, &mut line);
|
|
136
|
-
writer.write_all(line.as_bytes())?;
|
|
137
|
-
writer.write_all(b"\n")?;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
writer.flush()
|
|
141
|
-
}
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
## When to Create Fresh
|
|
145
|
-
|
|
146
|
-
```rust
|
|
147
|
-
// When ownership transfer is needed
|
|
148
|
-
fn produce_results() -> Vec<Vec<Item>> {
|
|
149
|
-
let mut results = Vec::new();
|
|
150
|
-
|
|
151
|
-
for batch in batches {
|
|
152
|
-
let processed: Vec<Item> = batch.process(); // Ownership transferred
|
|
153
|
-
results.push(processed); // Moved into results
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
results // Each inner Vec is independent
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// When thread safety requires it
|
|
160
|
-
std::thread::scope(|s| {
|
|
161
|
-
for _ in 0..4 {
|
|
162
|
-
s.spawn(|| {
|
|
163
|
-
let local_buffer = Vec::new(); // Thread-local, can't share
|
|
164
|
-
// ...
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
## See Also
|
|
171
|
-
|
|
172
|
-
- [mem-with-capacity](./mem-with-capacity.md) - Pre-allocating capacity
|
|
173
|
-
- [mem-clone-from](./mem-clone-from.md) - Reusing allocations when cloning
|
|
174
|
-
- [mem-write-over-format](./mem-write-over-format.md) - Avoiding format! allocations
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
# mem-smaller-integers
|
|
2
|
-
|
|
3
|
-
> Use appropriately-sized integers to reduce memory footprint
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Using `i64` when `i16` suffices wastes 6 bytes per value. In arrays, vectors, and structs with millions of instances, this waste compounds dramatically. Choosing the smallest integer type that fits your domain reduces memory usage and improves cache utilization.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
struct Pixel {
|
|
13
|
-
r: u64, // Color channels 0-255 = 8 bits needed
|
|
14
|
-
g: u64, // Using 64 bits = 8x waste
|
|
15
|
-
b: u64,
|
|
16
|
-
a: u64,
|
|
17
|
-
}
|
|
18
|
-
// Size: 32 bytes per pixel
|
|
19
|
-
|
|
20
|
-
struct HttpStatus {
|
|
21
|
-
code: i32, // HTTP codes 100-599 = 10 bits needed
|
|
22
|
-
version: i32, // HTTP 1.0, 1.1, 2, 3 = 2 bits needed
|
|
23
|
-
}
|
|
24
|
-
// Size: 8 bytes per status
|
|
25
|
-
|
|
26
|
-
struct GeoPoint {
|
|
27
|
-
lat: f64, // -90 to 90
|
|
28
|
-
lon: f64, // -180 to 180
|
|
29
|
-
}
|
|
30
|
-
// Often f32 precision is sufficient for display
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Good
|
|
34
|
-
|
|
35
|
-
```rust
|
|
36
|
-
struct Pixel {
|
|
37
|
-
r: u8,
|
|
38
|
-
g: u8,
|
|
39
|
-
b: u8,
|
|
40
|
-
a: u8,
|
|
41
|
-
}
|
|
42
|
-
// Size: 4 bytes per pixel (8x smaller!)
|
|
43
|
-
|
|
44
|
-
struct HttpStatus {
|
|
45
|
-
code: u16, // 100-599 fits in u16
|
|
46
|
-
version: u8, // 1, 2, 3 fits in u8
|
|
47
|
-
}
|
|
48
|
-
// Size: 3 bytes (+ 1 padding = 4 bytes)
|
|
49
|
-
|
|
50
|
-
struct GeoPoint {
|
|
51
|
-
lat: f32, // ~7 decimal digits precision
|
|
52
|
-
lon: f32, // Sufficient for most geo applications
|
|
53
|
-
}
|
|
54
|
-
// Size: 8 bytes vs 16 bytes
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Integer Size Reference
|
|
58
|
-
|
|
59
|
-
| Type | Range | Use For |
|
|
60
|
-
|------|-------|---------|
|
|
61
|
-
| `u8` | 0 to 255 | Bytes, small counts, flags |
|
|
62
|
-
| `i8` | -128 to 127 | Small signed values |
|
|
63
|
-
| `u16` | 0 to 65,535 | Port numbers, small indices |
|
|
64
|
-
| `i16` | -32,768 to 32,767 | Audio samples |
|
|
65
|
-
| `u32` | 0 to 4 billion | Array indices, timestamps (seconds) |
|
|
66
|
-
| `i32` | ±2 billion | General integers, file offsets |
|
|
67
|
-
| `u64` | 0 to 18 quintillion | Large counts, nanosecond timestamps |
|
|
68
|
-
| `usize` | Platform-dependent | Array indexing (required by Rust) |
|
|
69
|
-
|
|
70
|
-
## Struct Packing
|
|
71
|
-
|
|
72
|
-
```rust
|
|
73
|
-
use std::mem::size_of;
|
|
74
|
-
|
|
75
|
-
// Poor ordering - 24 bytes due to padding
|
|
76
|
-
struct Wasteful {
|
|
77
|
-
a: u8, // 1 byte + 7 padding
|
|
78
|
-
b: u64, // 8 bytes
|
|
79
|
-
c: u8, // 1 byte + 7 padding
|
|
80
|
-
}
|
|
81
|
-
assert_eq!(size_of::<Wasteful>(), 24);
|
|
82
|
-
|
|
83
|
-
// Better ordering - 16 bytes
|
|
84
|
-
struct Efficient {
|
|
85
|
-
b: u64, // 8 bytes (aligned)
|
|
86
|
-
a: u8, // 1 byte
|
|
87
|
-
c: u8, // 1 byte + 6 padding
|
|
88
|
-
}
|
|
89
|
-
assert_eq!(size_of::<Efficient>(), 16);
|
|
90
|
-
|
|
91
|
-
// Even better with smaller types - 10 bytes
|
|
92
|
-
struct Compact {
|
|
93
|
-
b: u32, // 4 bytes (if u32 suffices)
|
|
94
|
-
a: u8, // 1 byte
|
|
95
|
-
c: u8, // 1 byte
|
|
96
|
-
}
|
|
97
|
-
assert_eq!(size_of::<Compact>(), 8); // With padding
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## Conversion Safety
|
|
101
|
-
|
|
102
|
-
```rust
|
|
103
|
-
// Safe: always succeeds (widening)
|
|
104
|
-
let small: u8 = 42;
|
|
105
|
-
let big: u32 = small.into();
|
|
106
|
-
|
|
107
|
-
// Fallible: may overflow (narrowing)
|
|
108
|
-
let big: u32 = 1000;
|
|
109
|
-
let small: u8 = big.try_into().expect("value out of range");
|
|
110
|
-
|
|
111
|
-
// Or use checked conversion
|
|
112
|
-
if let Ok(small) = u8::try_from(big) {
|
|
113
|
-
use_small(small);
|
|
114
|
-
} else {
|
|
115
|
-
handle_overflow();
|
|
116
|
-
}
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
## Bitflags for Boolean Sets
|
|
120
|
-
|
|
121
|
-
```rust
|
|
122
|
-
use bitflags::bitflags;
|
|
123
|
-
|
|
124
|
-
// Instead of 8 separate bool fields (8 bytes minimum)
|
|
125
|
-
bitflags! {
|
|
126
|
-
struct Permissions: u8 {
|
|
127
|
-
const READ = 0b0000_0001;
|
|
128
|
-
const WRITE = 0b0000_0010;
|
|
129
|
-
const EXECUTE = 0b0000_0100;
|
|
130
|
-
const DELETE = 0b0000_1000;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
// All 8 flags in 1 byte!
|
|
134
|
-
|
|
135
|
-
let perms = Permissions::READ | Permissions::WRITE;
|
|
136
|
-
if perms.contains(Permissions::READ) {
|
|
137
|
-
// ...
|
|
138
|
-
}
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
## NonZero Types for Option Optimization
|
|
142
|
-
|
|
143
|
-
```rust
|
|
144
|
-
use std::num::NonZeroU64;
|
|
145
|
-
|
|
146
|
-
// Option<u64> = 16 bytes (no null pointer optimization)
|
|
147
|
-
assert_eq!(size_of::<Option<u64>>(), 16);
|
|
148
|
-
|
|
149
|
-
// Option<NonZeroU64> = 8 bytes (0 represents None)
|
|
150
|
-
assert_eq!(size_of::<Option<NonZeroU64>>(), 8);
|
|
151
|
-
|
|
152
|
-
let id: Option<NonZeroU64> = NonZeroU64::new(42);
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
## See Also
|
|
156
|
-
|
|
157
|
-
- [mem-box-large-variant](./mem-box-large-variant.md) - Optimizing enum sizes
|
|
158
|
-
- [mem-assert-type-size](./mem-assert-type-size.md) - Compile-time size checks
|
|
159
|
-
- [type-newtype-ids](./type-newtype-ids.md) - Type safety for integer IDs
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
# mem-smallvec
|
|
2
|
-
|
|
3
|
-
> Use `SmallVec` for usually-small collections
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
`SmallVec<[T; N]>` stores up to N elements inline (on the stack), only allocating on the heap when the size exceeds N. This eliminates heap allocations for the common case while still allowing growth when needed.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
// Always heap-allocates, even for 1-2 elements
|
|
13
|
-
fn get_path_components(path: &str) -> Vec<&str> {
|
|
14
|
-
path.split('/').collect() // Usually 2-4 components
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Always heap-allocates for error list
|
|
18
|
-
fn validate(input: &Input) -> Vec<ValidationError> {
|
|
19
|
-
let mut errors = Vec::new(); // Usually 0-3 errors
|
|
20
|
-
// validation logic...
|
|
21
|
-
errors
|
|
22
|
-
}
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Good
|
|
26
|
-
|
|
27
|
-
```rust
|
|
28
|
-
use smallvec::{smallvec, SmallVec};
|
|
29
|
-
|
|
30
|
-
// Stack-allocated for typical paths (1-8 components)
|
|
31
|
-
fn get_path_components(path: &str) -> SmallVec<[&str; 8]> {
|
|
32
|
-
path.split('/').collect()
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Stack-allocated for typical error counts
|
|
36
|
-
fn validate(input: &Input) -> SmallVec<[ValidationError; 4]> {
|
|
37
|
-
let mut errors = SmallVec::new();
|
|
38
|
-
// validation logic...
|
|
39
|
-
errors
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Using smallvec! macro
|
|
43
|
-
let v: SmallVec<[i32; 4]> = smallvec![1, 2, 3];
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Choosing Capacity N
|
|
47
|
-
|
|
48
|
-
```rust
|
|
49
|
-
// Measure your actual data distribution!
|
|
50
|
-
// Guidelines:
|
|
51
|
-
|
|
52
|
-
// Path components: 4-8 (most paths are shallow)
|
|
53
|
-
type PathParts<'a> = SmallVec<[&'a str; 8]>;
|
|
54
|
-
|
|
55
|
-
// Function arguments: 4-8 (most functions have few args)
|
|
56
|
-
type Args = SmallVec<[Arg; 8]>;
|
|
57
|
-
|
|
58
|
-
// AST children: 2-4 (binary ops, if/else, etc.)
|
|
59
|
-
type Children = SmallVec<[Node; 4]>;
|
|
60
|
-
|
|
61
|
-
// Error accumulation: 2-4 (most inputs have few errors)
|
|
62
|
-
type Errors = SmallVec<[Error; 4]>;
|
|
63
|
-
|
|
64
|
-
// Attribute lists: 4-8 (most items have few attributes)
|
|
65
|
-
type Attrs = SmallVec<[Attribute; 8]>;
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
## Evidence from rust-analyzer
|
|
69
|
-
|
|
70
|
-
```rust
|
|
71
|
-
// https://github.com/rust-lang/rust/blob/main/compiler/rustc_expand/src/base.rs
|
|
72
|
-
macro_rules! make_stmts_default {
|
|
73
|
-
($me:expr) => {
|
|
74
|
-
$me.make_expr().map(|e| {
|
|
75
|
-
smallvec![ast::Stmt {
|
|
76
|
-
id: ast::DUMMY_NODE_ID,
|
|
77
|
-
span: e.span,
|
|
78
|
-
kind: ast::StmtKind::Expr(e),
|
|
79
|
-
}]
|
|
80
|
-
})
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
## Trade-offs
|
|
86
|
-
|
|
87
|
-
```rust
|
|
88
|
-
// SmallVec is slightly larger than Vec
|
|
89
|
-
use std::mem::size_of;
|
|
90
|
-
// Vec<i32>: 24 bytes (ptr + len + cap)
|
|
91
|
-
// SmallVec<[i32; 4]>: 32 bytes (inline storage + len + discriminant)
|
|
92
|
-
|
|
93
|
-
// SmallVec has branching overhead on every operation
|
|
94
|
-
// (must check if inline or heap)
|
|
95
|
-
|
|
96
|
-
// Profile to verify benefit!
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## When to Use SmallVec vs Alternatives
|
|
100
|
-
|
|
101
|
-
| Situation | Use |
|
|
102
|
-
|-----------|-----|
|
|
103
|
-
| Usually small, sometimes large | `SmallVec<[T; N]>` |
|
|
104
|
-
| Always small, fixed max | `ArrayVec<T, N>` |
|
|
105
|
-
| Rarely grows past initial | `Vec::with_capacity` |
|
|
106
|
-
| No `unsafe` allowed | `TinyVec` |
|
|
107
|
-
| Often empty | `ThinVec` |
|
|
108
|
-
|
|
109
|
-
## ArrayVec Alternative
|
|
110
|
-
|
|
111
|
-
```rust
|
|
112
|
-
use arrayvec::ArrayVec;
|
|
113
|
-
|
|
114
|
-
// Fixed maximum capacity, never heap allocates
|
|
115
|
-
// Panics if you exceed capacity
|
|
116
|
-
fn parse_rgb(s: &str) -> ArrayVec<u8, 3> {
|
|
117
|
-
let mut components = ArrayVec::new();
|
|
118
|
-
for part in s.split(',').take(3) {
|
|
119
|
-
components.push(part.parse().unwrap());
|
|
120
|
-
}
|
|
121
|
-
components
|
|
122
|
-
}
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
## TinyVec (No Unsafe)
|
|
126
|
-
|
|
127
|
-
```rust
|
|
128
|
-
use tinyvec::{tiny_vec, TinyVec};
|
|
129
|
-
|
|
130
|
-
// Same concept as SmallVec but 100% safe code
|
|
131
|
-
let v: TinyVec<[i32; 4]> = tiny_vec![1, 2, 3];
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## See Also
|
|
135
|
-
|
|
136
|
-
- [mem-arrayvec](mem-arrayvec.md) - Use ArrayVec for fixed-max collections
|
|
137
|
-
- [mem-with-capacity](mem-with-capacity.md) - Pre-allocate when size is known
|
|
138
|
-
- [mem-thinvec](mem-thinvec.md) - Use ThinVec for often-empty vectors
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
# mem-thinvec
|
|
2
|
-
|
|
3
|
-
> Use `ThinVec<T>` for nullable collections with minimal overhead
|
|
4
|
-
|
|
5
|
-
## Why It Matters
|
|
6
|
-
|
|
7
|
-
Standard `Vec<T>` is 24 bytes even when empty. `ThinVec` from Mozilla's `thin_vec` crate uses a single pointer (8 bytes), storing length and capacity inline with the heap allocation. For Option<Vec<T>> patterns or structs with many optional vecs, this significantly reduces memory overhead.
|
|
8
|
-
|
|
9
|
-
## Bad
|
|
10
|
-
|
|
11
|
-
```rust
|
|
12
|
-
struct TreeNode {
|
|
13
|
-
value: i32,
|
|
14
|
-
// Each node pays 24 bytes for children, even leaves
|
|
15
|
-
children: Vec<TreeNode>, // Most nodes are leaves with empty Vec
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Or using Option<Vec<T>>
|
|
19
|
-
struct SparseData {
|
|
20
|
-
// Option<Vec> = 24 bytes (Vec is never null-pointer optimized)
|
|
21
|
-
tags: Option<Vec<String>>,
|
|
22
|
-
metadata: Option<Vec<Metadata>>,
|
|
23
|
-
// 48 bytes for usually-None fields
|
|
24
|
-
}
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Good
|
|
28
|
-
|
|
29
|
-
```rust
|
|
30
|
-
use thin_vec::ThinVec;
|
|
31
|
-
|
|
32
|
-
struct TreeNode {
|
|
33
|
-
value: i32,
|
|
34
|
-
// Empty ThinVec is just a null pointer - 8 bytes
|
|
35
|
-
children: ThinVec<TreeNode>,
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
struct SparseData {
|
|
39
|
-
// ThinVec empty = 8 bytes each
|
|
40
|
-
tags: ThinVec<String>,
|
|
41
|
-
metadata: ThinVec<Metadata>,
|
|
42
|
-
// 16 bytes vs 48 bytes
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Memory Layout
|
|
47
|
-
|
|
48
|
-
```rust
|
|
49
|
-
use std::mem::size_of;
|
|
50
|
-
|
|
51
|
-
// Standard Vec: always 24 bytes
|
|
52
|
-
assert_eq!(size_of::<Vec<u8>>(), 24);
|
|
53
|
-
assert_eq!(size_of::<Option<Vec<u8>>>(), 24); // No NPO benefit
|
|
54
|
-
|
|
55
|
-
// ThinVec: 8 bytes (one pointer)
|
|
56
|
-
use thin_vec::ThinVec;
|
|
57
|
-
assert_eq!(size_of::<ThinVec<u8>>(), 8);
|
|
58
|
-
assert_eq!(size_of::<Option<ThinVec<u8>>>(), 8); // Option is free!
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## ThinVec vs Vec
|
|
62
|
-
|
|
63
|
-
| Feature | `Vec<T>` | `ThinVec<T>` |
|
|
64
|
-
|---------|----------|--------------|
|
|
65
|
-
| Size (empty) | 24 bytes | 8 bytes |
|
|
66
|
-
| Size (non-empty) | 24 bytes | 8 bytes (header on heap) |
|
|
67
|
-
| Option<T> optimization | No | Yes |
|
|
68
|
-
| Cache locality | Better (len/cap on stack) | Worse (len/cap on heap) |
|
|
69
|
-
| Iteration speed | Faster | Slightly slower |
|
|
70
|
-
| API compatibility | Full | Vec-like |
|
|
71
|
-
|
|
72
|
-
## When to Use ThinVec
|
|
73
|
-
|
|
74
|
-
```rust
|
|
75
|
-
// ✅ Good: Many instances, often empty
|
|
76
|
-
struct SparseGraph {
|
|
77
|
-
nodes: Vec<Node>,
|
|
78
|
-
// Most edges lists are empty or small
|
|
79
|
-
edges: Vec<ThinVec<EdgeId>>, // Saves 16 bytes per node
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// ✅ Good: Nullable collection field
|
|
83
|
-
struct Document {
|
|
84
|
-
content: String,
|
|
85
|
-
attachments: ThinVec<Attachment>, // Often empty
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// ❌ Avoid: Hot loops, performance-critical iteration
|
|
89
|
-
fn process_hot_path(data: &ThinVec<Item>) {
|
|
90
|
-
// Every length check goes through pointer indirection
|
|
91
|
-
for item in data { // Vec would be faster here
|
|
92
|
-
process(item);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// ❌ Avoid: Few instances
|
|
97
|
-
fn main() {
|
|
98
|
-
let single_vec: ThinVec<i32> = ThinVec::new();
|
|
99
|
-
// Saving 16 bytes once is meaningless
|
|
100
|
-
}
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
## API Compatibility
|
|
104
|
-
|
|
105
|
-
```rust
|
|
106
|
-
use thin_vec::{ThinVec, thin_vec};
|
|
107
|
-
|
|
108
|
-
// Constructor macro
|
|
109
|
-
let v: ThinVec<i32> = thin_vec![1, 2, 3];
|
|
110
|
-
|
|
111
|
-
// Familiar Vec-like API
|
|
112
|
-
let mut v = ThinVec::new();
|
|
113
|
-
v.push(1);
|
|
114
|
-
v.push(2);
|
|
115
|
-
v.extend([3, 4, 5]);
|
|
116
|
-
v.pop();
|
|
117
|
-
|
|
118
|
-
// Iteration
|
|
119
|
-
for item in &v {
|
|
120
|
-
println!("{}", item);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Slicing
|
|
124
|
-
let slice: &[i32] = &v[..];
|
|
125
|
-
|
|
126
|
-
// Conversion
|
|
127
|
-
let vec: Vec<i32> = v.into();
|
|
128
|
-
let thin: ThinVec<i32> = vec.into();
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
## Cargo.toml
|
|
132
|
-
|
|
133
|
-
```toml
|
|
134
|
-
[dependencies]
|
|
135
|
-
thin-vec = "0.2"
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## See Also
|
|
139
|
-
|
|
140
|
-
- [mem-smallvec](./mem-smallvec.md) - Stack-allocated small vecs
|
|
141
|
-
- [mem-boxed-slice](./mem-boxed-slice.md) - Fixed-size heap slices
|
|
142
|
-
- [mem-with-capacity](./mem-with-capacity.md) - Pre-allocation strategies
|