diff --git a/API.md b/API.md deleted file mode 100644 index b221cf3..0000000 --- a/API.md +++ /dev/null @@ -1,72 +0,0 @@ -# API compatibility - -CheetahString 3.1 keeps the stable 3.x source surface while tightening the -private implementation. Public stable methods, traits, variants, aliases, and -return types are not removed or renamed in this release line. - -There is one documented safety exception: the published -`experimental-packed` module was removed after strict-provenance Miri exposed -undefined behavior in its safe API. The Cargo feature name remains as a no-op -for dependency resolution, but code importing `cheetah_string::packed` must -migrate to `CheetahString` or `CheetahBuilder`. A registry comparison against -3.0.0 therefore reports the expected removal of the experimental module, its -constant, and `PackedCheetahString`. - -## Pattern contract - -`starts_with`, `ends_with`, and `contains` accept the sealed `StrPattern` types: - -| Pattern | Meaning | -|---|---| -| `char` | one Unicode scalar value | -| `&str` | borrowed string pattern | -| `&String` | borrowed owned string pattern | - -External `StrPattern` implementations are rejected by the sealed supertrait. -Query methods classify supported values through a private enum. The hidden -`StrPattern::as_str_pattern` method and its dispatch value remain callable only -as 3.1 compatibility surfaces; the query implementation does not depend on -them. - -`split_char` exposes a double-ended standard iterator. `split_str` remains -forward-only because standard string-pattern splitting cannot guarantee reverse -iteration. These capabilities are expressed by the return types rather than by -a runtime panic path. - -## Error contract - -The operations intentionally return the most precise existing error type: - -| Operation | Error type | Buffer recovery | -|---|---|---| -| `try_from_bytes`, `try_from_vec`, `try_from_arc_vec` | `core::str::Utf8Error` | No | -| `try_from_bytes_buf` | `core::str::Utf8Error` | No | -| `try_copy_from_bytes` | `FromUtf8BytesError` | Yes, via `into_bytes` or `into_parts` | -| `CheetahBytes::try_into_string` | `core::str::Utf8Error` | No | -| `try_substring` | `cheetah_string::Error` through `Result` | Not applicable | - -`Error::Utf8Error` and `From` remain available for existing callers -that aggregate errors into the crate's compatibility error type. UTF-8 -constructors continue to return `Utf8Error` directly; 3.1 does not rewrite their -signatures. Range variants remain exhaustive and unchanged for existing match -expressions. - -## Automated compatibility gate - -`.github/workflows/api-compatibility.yml` runs `cargo-semver-checks` with -minor-release rules against `origin/main` and all features. This protects each -new pull request after the packed retirement baseline; it does not conceal the -approved experimental safety removal relative to the published 3.0.0 crate. -The repository also compiles a downstream-style test that calls the hidden -compatibility method and checks the exact constructor and substring result -types. - -Local reproduction: - -```bash -cargo semver-checks check-release \ - --baseline-rev origin/main \ - --all-features \ - --release-type minor -cargo test --test api_contract --all-features -``` diff --git a/LAYOUT.md b/LAYOUT.md deleted file mode 100644 index 7acabef..0000000 --- a/LAYOUT.md +++ /dev/null @@ -1,55 +0,0 @@ -# Stable layout contract - -`CheetahString` keeps three storage modes in a private Rust enum: - -| Mode | Payload | Ownership | -|---|---|---| -| Inline | constrained length plus 23 UTF-8 bytes | stored in the value | -| Static | `&'static str` | borrowed forever | -| Shared | `Arc` | immutable reference-counted ownership | - -The inline length is a `repr(u8)` enum with exactly 24 valid values, from 0 -through 23. Its other bit patterns are invalid discriminants. Rust can use those -invalid patterns as niches for the outer storage variants and for `Option`, so -the largest 24-byte payload does not require a separate discriminant byte. - -This design preserves pointer provenance. It does not cast pointers to integers, -reconstruct pointers, use a union, implement manual drop logic, or add an unsafe -block. Static and shared values remain ordinary references and `Arc` values. - -## Enforced sizes - -The supported 32-bit and 64-bit targets enforce: - -| Type | Size | -|---|---:| -| `CheetahString` | 24 bytes | -| `Option` | 24 bytes | -| 10,000 `CheetahString` vector slots | 240,000 bytes | -| 10,000 `(CheetahString, u64)` map-entry payloads on 64-bit | 320,000 bytes | - -The previous 64-bit representation used 320,000 bytes for 10,000 vector slots; -the compact representation saves 80,000 bytes, or 25%, before allocator -overhead. Its vector slot size now matches `String`, while long clones retain -the O(1), zero-allocation `Arc` behavior that `String` does not provide. - -Rust enum layout is not a public ABI guarantee. The project therefore treats -24 bytes as a tested performance contract rather than an FFI promise. The CI -matrix checks stable and nightly toolchains, the Rust 1.95 packaged consumer, -and a 32-bit target. Any compiler that stops applying the required niche -optimization fails the layout gate instead of silently changing the footprint. - -## Verification - -```bash -cargo test --test layout_snapshot --all-features -- --nocapture -cargo test --test allocation_contract --all-features -- --test-threads=1 -cargo bench --bench shared_backing -- __allocation_evidence_only__ --noplot \ - 2>&1 | tee target/allocation-evidence.log -python scripts/verify-allocation-evidence.py target/allocation-evidence.log -``` - -Miri remains the behavioral provenance check for the stable representation. -The layout snapshot and schema-v3 benchmark evidence independently enforce the -object size, container slot footprint, allocation counts, and shared-pointer -retention contract. diff --git a/PERFORMANCE.md b/PERFORMANCE.md deleted file mode 100644 index 50dc185..0000000 --- a/PERFORMANCE.md +++ /dev/null @@ -1,57 +0,0 @@ -# Performance contracts - -CheetahString separates deterministic performance contracts from timing -measurements. Allocation counts and object layout are merge/release gates; -Criterion timing and RSS observations are diagnostic because hosted runner -noise cannot establish a portable latency threshold. - -## Enforced 64-bit contracts - -| Operation | Maximum allocation events | Additional invariant | -|---|---:|---| -| Inline construction | 0 | UTF-8 length is at most 23 bytes | -| Static construction | 0 | Explicit static input remains borrowed | -| Long `Arc` adoption | 0 | Payload pointer is retained | -| `char` construction | 0 | Every Unicode scalar remains inline | -| Concatenation with a result of at most 23 bytes | 0 | Result remains inline | -| Long shared clone | 0 | Payload pointer is shared | -| Long borrowed construction | 1 | One live `Arc` backing | -| Exact-capacity owned/builder freeze | 1 | One live `Arc` backing | -| Spare-capacity owned/builder freeze | 2 | Shrink/reallocation plus `Arc` backing | -| `CheetahString` object size | N/A | 24 bytes on supported 32-bit and 64-bit targets | -| `Option` object size | N/A | 24 bytes on supported 32-bit and 64-bit targets | -| 10,000 vector element slots | N/A | 240,000 bytes; 80,000 below the prior contract | -| 10,000 `(CheetahString, u64)` payloads | N/A | 320,000 bytes; equal to `(String, u64)` | - -The allocation count includes allocation and reallocation events during the -measured conversion. It is intentionally different from the number of live -allocations retained by the result. - -## Reproducing the gates - -Run the direct contracts: - -```bash -cargo test --test allocation_contract --all-features -- --test-threads=1 -cargo test --test layout_snapshot --all-features -- --nocapture -``` - -Capture and validate the independent benchmark evidence: - -```bash -cargo bench --bench shared_backing -- __allocation_evidence_only__ --noplot \ - 2>&1 | tee target/allocation-evidence.log -python scripts/verify-allocation-evidence.py target/allocation-evidence.log -``` - -The verifier requires one schema-v3 `SHARED_BACKING_EVIDENCE` record and fails -closed when a required field is absent, an allocation count regresses, the -64-bit layout or downstream slot footprint changes, or long `Arc` input -does not retain its pointer. - -## Timing policy - -Criterion groups remain useful for comparing construction, cloning, inline -fast paths, and RocketMQ-shaped map workloads on the same machine. Their raw -timings and RSS samples must be reported with toolchain, CPU, operating system, -feature set, and source revision. They are not used as cross-run release gates. diff --git a/README.md b/README.md index b7f1e94..de23e3f 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,8 @@ On supported 32-bit and 64-bit targets, both `CheetahString` and `Option` occupy 24 bytes. A 10,000-element vector therefore uses 240,000 bytes of element slots instead of the previous 320,000-byte contract. This is achieved with safe Rust enum niches; string pointers are never converted -to integers. See [Stable layout](LAYOUT.md) for the exact representation and -portability gate. +to integers. `tests/layout_snapshot.rs` and `tests/allocation_contract.rs` +enforce the representation, container footprint, and portability contract. The representation has no mutable `Owned(String)` state. Construction history therefore cannot change clone complexity. Use: @@ -198,9 +198,8 @@ cargo bench --bench mq_topic Hosted-runner and local benchmark results are diagnostic; they do not independently establish a release-grade performance pass. The versioned allocation and layout tests are the deterministic performance contracts. -See [Performance contracts](PERFORMANCE.md) for the exact enforced budgets and -the distinction between deterministic gates and diagnostic timing results, and -[Stable layout](LAYOUT.md) for the provenance-preserving 24-byte representation. +`scripts/verify-allocation-evidence.py` independently validates the schema-v3 +allocation record emitted by the shared-backing benchmark. ## Safety and portability @@ -215,12 +214,13 @@ CI enforces the Rust 1.95 packaged-consumer matrix, warning-free rustdoc, locked dependency auditing, and repository workflow contracts. The Safety workflow runs Miri over the stable text/byte invariants and compiles every libFuzzer target with AddressSanitizer on pull requests and on a weekly -schedule. See [Safety model](SAFETY.md) for the maintained unsafe-boundary -inventory and local verification commands. +schedule. The maintained commands and toolchain setup are encoded directly in +`.github/workflows/safety.yml`; unsafe constructor obligations remain next to +their public APIs in `src/cheetah_string/construct.rs` and `src/bytes.rs`. -Pattern and error signatures follow the source-compatible 3.1 policy described -in [API compatibility](API.md). A dedicated workflow compares every pull request -with `origin/main` under minor-release semver rules. +Pattern and error signatures are covered by `tests/api_contract.rs`. The +dedicated `.github/workflows/api-compatibility.yml` workflow compares every pull +request with `origin/main` under minor-release semver rules. ## Projects using CheetahString diff --git a/SAFETY.md b/SAFETY.md deleted file mode 100644 index 0531bf8..0000000 --- a/SAFETY.md +++ /dev/null @@ -1,56 +0,0 @@ -# Safety model - -This file records the unsafe boundaries that remain in the stable -`CheetahString` 3.1 implementation. The retired packed representation is not -part of this model and is not exported by the crate. - -## Core invariants - -- Every `CheetahString` is valid UTF-8 for its complete lifetime. -- Inline length is represented by a private 0-through-23 enum and never exceeds - the 23-byte inline buffer. Its invalid discriminants are compiler layout - niches; they are never constructed as inline lengths. -- Static storage contains a valid `&'static str`. -- Shared storage is an owned `Arc` and preserves pointer provenance. -- `CheetahBytes` has byte semantics and does not imply UTF-8. - -## Unsafe boundary inventory - -| Boundary | Caller obligation | Internal proof | -|---|---|---| -| `CheetahString::from_utf8_unchecked_vec` | The complete vector is valid UTF-8. | The private unsafe helper either copies at most 23 validated bytes inline or converts the owned vector to `String` before freezing it. | -| `CheetahString::from_utf8_unchecked_bytes` | The complete slice is valid UTF-8. | The validated `str` view is immediately copied into canonical storage. | -| `CheetahString::from_utf8_unchecked_arc_vec` | The complete shared vector is valid UTF-8. | Unique input follows the vector boundary; shared input is copied through the validated slice boundary. | -| `CheetahString::from_utf8_unchecked_bytes_buf` | The complete `bytes::Bytes` payload is valid UTF-8. | The payload is copied through the validated slice boundary. | -| `CheetahBytes::into_string_unchecked` | The complete byte payload is valid UTF-8. | The obligation is forwarded to the `bytes::Bytes` text boundary. | -| SSE2 equality helper | SSE2 is available and both slices have equal length. | Runtime/target gating establishes SSE2, and each unaligned 16-byte load is guarded by the loop bounds. | - -The private helpers whose names contain `validated` are themselves `unsafe fn`. -Safe constructors perform UTF-8 validation before entering those helpers; -public unchecked constructors forward their documented caller contract in an -explicit unsafe block. - -The 24-byte representation does not add an unsafe boundary. `Static` remains a -normal `&'static str`, `Shared` remains a normal `Arc`, and the outer Rust -enum uses the constrained inline-length discriminants as niches. No pointer is -converted to an integer or reconstructed. Layout snapshots gate the compiler -optimization separately from Miri's behavioral provenance checks. - -## Verification - -Run the stable representation under Miri: - -```bash -cargo +nightly miri test --lib --no-default-features -cargo +nightly miri test --test basic --no-default-features -cargo +nightly miri test --test bytes --features bytes -``` - -Compile all fuzz targets with libFuzzer and AddressSanitizer: - -```bash -cargo +nightly fuzz build -``` - -The same commands are encoded in `.github/workflows/safety.yml` with pinned -third-party actions. diff --git a/cheetah-string-architecture-performance-report.html b/cheetah-string-architecture-performance-report.html deleted file mode 100644 index dad6111..0000000 --- a/cheetah-string-architecture-performance-report.html +++ /dev/null @@ -1,645 +0,0 @@ - - - - - - - CheetahString 3.1 架构与性能复审 · 95/100 - - - - - -
-
-
-
-
Architecture × Performance × Evidence
-

CheetahString
深度审计

-

3.1 已把最初审计中的安全、布局、MSRV、分配、API 与发布证据缺口逐项闭合:保持 23B SSO 与 Arc<str> 克隆语义,同时用安全 Rust niche 将对象压到 24B。它仍不是所有写入型负载上的 String 替代品,但已具备可验证的发布级工程闭环。

-
- 203 / 203 Rust tests - 24B object + 23B SSO - 61 Miri tests - Rust 1.95 matrix: PASS - stable API gate: PASS -
-
-
-
95/ 100 · 综合评分
-
-
-
- -
-
-
-
00 / VERDICT
-

结论先行

评分对象是合并后的完整 3.1 仓库。置信度:高;布局、分配、MSRV 与 API 结论由门禁证明,Criterion 时序仍只作为本机诊断。

-
-
建议使用:协议字段、路由键、缓存键等“构造一次、读取和克隆很多次”的 UTF-8 值;已有长 Arc<str> 可零拷贝接管。
保留 String持续追加、频繁变换、一次性消费,或必须保留 spare capacity 的写入路径。
-
-
核心架构
成熟

Inline / Static / Shared 三态、Builder 写入边界、byte/text 所有权与私有 pattern dispatch 相互一致;兼容 shim 不参与内部实现。

-
性能画像
可预测

24B 槽位与 String 等大;长 clone、Arc<str> adoption、char 与短 concat 均为 0 allocation。长 freeze/transform 仍需复制。

-
发布成熟度
闭环

5 套工作流覆盖 MSRV、文档、Miri、fuzz build、audit、性能和 semver;发布在校验与 digest 检查后才创建 tag。

-
-
-
- -
-
-
-
01 / SCORE
-

100 分评分账本

权重向架构与性能倾斜(合计 55 分);每一处扣分都能落到源码、命令结果或本机测量。

-
-
-
核心架构与 API三态模型、模块职责、3.1 兼容面
24/25
-
运行时性能克隆、搜索、构造、真实形状负载
28/30
-
内存与分配24B 对象、23B SSO、freeze、共享边界
15/15
-
正确性与安全测试、Miri、unsafe、feature 风险
14/15
-
工程证据与发布CI、MSRV、文档、可复现性、供应链
14/15
-
-

总分 95/100。仍使用最初报告的独立 rubric:退役存在 UB 的实验 packed API、兼容 shim 与既有 Error 聚合模型合计扣 1 分;长 transform/substring/freeze 的复制成本扣 2 分;CI 只编译 fuzz target、尚无持续限时 fuzz 执行扣 1 分;跨机器时序没有固定 CPU 阻断门禁再扣 1 分。评分不依赖已删除的旧自评分脚本。

-
-
- -
-
-
-
02 / ARCH
-

架构:用不可变性买下确定的克隆成本

根模块是薄门面,核心类型再按 construct / convert / query / pattern / repr / traits 分层。真正的架构中心不是 SSO,而是“构造历史不能改变 clone 复杂度”。

-
- -
-
-
-
&str / String / Arc<str> / Vec<u8>safe bytes 先做 UTF-8 validation
-
CheetahBuilderString 承担 mutation / reserve / clear
-
&'static str显式 static constructor
-
-
-
-
length / ownership gate普通构造:≤23B inline;长值 freeze
-
finish()mutable → immutable;长值复制进 Arc<str>
-
from_static_str()无论长度,直接选择 Static
-
-
-
-
Inline受限 len enum + [u8; 23] · 0 heap alloc
-
Static&'static str · 0 heap alloc
-
SharedArc<str> · clone = atomic refcount
-
-
-
- -
-

设计已闭合的部分

  • 稳定表示只有 Inline / Static / Shared 三态,字段私有,文本语义统一。
  • Builder 把可变容量从 value type 剥离,避免构造历史改变 clone 复杂度。
  • From<Arc<str>> 对长值保留 payload pointer;短值仍 canonicalize 为 Inline。
  • lines() 暴露 DoubleEnded / Clone / Fused;char 与 string split 在类型层表达能力。
  • pattern 查询使用私有 sealed classifier;3.1 兼容方法仅作为桥接面保留。
  • 错误返回矩阵、静态优先级和复制边界已在 API.md 中明确。
-

仍保留的架构权衡

  • 显式 from_static_str 总是 Static,而非按长度 Inline;这是记录清楚的 ownership 优先规则。
  • from(String)finish() 必须把可变 payload 冻结为 Arc<str>,不能做到零复制。
  • substring 产生独立值,不保存 shared slice 的 offset/length,因此长片段需分配复制。
  • 3.1 为源码兼容继续保留隐藏 pattern dispatch 与 umbrella Error;内部实现已与其解耦。
  • experimental-simd 的收益依操作和长度而异,保持默认关闭。
-
- -
“零分配克隆/接管”不等于“所有构造零成本”。Arc<str> adoption 为 0 allocation;长 borrowed / exact-capacity String freeze 为 1 次;spare-capacity String / Builder freeze 为 2 次。三条路径都由直接计数契约和 schema-v3 benchmark evidence 验证,而非同构推断。
- -

稳定复杂度模型

-
- - - - - - - - - - -
操作Inline / StaticShared架构含义
cloneO(1),复制有界 24B / 指针O(1),Arc 原子计数0 allocation;长值 payload pointer 不变
as_str / lenO(1)O(1)一次 enum dispatch,可内联
from(&str)O(k≤23),0 allocO(n),1 live allocation长 borrowed input 复制进 Arc
from(Arc<str>)O(k≤23),0 allocO(1),0 alloc长值 ownership-preserving;pointer 不变
from(String) / finishO(k≤23),结果 inlineO(n),1–2 allocation eventsspare capacity 先 shrink/realloc
substringO(k),复制O(k),长结果 1 alloc不是 shared slice
Add / transform≤23B concat 直接栈上,0 allocO(n+m);长结果经 String freeze长变换通常应先保留 String/Builder
-
-
- -
-
-
-
03 / PERF
-

性能:读多写少模型成立,构造边界仍需按负载取舍

当前提交的 Criterion 本地诊断:Windows 11 / i7-11700K / rustc 1.96.1。评分只依赖可重复的布局与分配契约;未固定频率、CPU affinity 与双向 base/head 的纳秒数据只用于解释趋势。

-
- -
-
1 KiB clone
26.49 ns

String 为 246.10 ns,本机约 9.29×;共享长值 clone 为 O(1) 且零分配。

-
25B borrowed construction
55.75 ns

String 为 40.69 ns;刚越过 23B inline 边界时,本机 median 慢约 37%

-
10k × 25B topic insert
653.37 µs

String 为 614.94 µs;本机 median 差约 6.3%,95% CI 重叠,判定为近似持平。

-
- -

克隆曲线:23B 内联是有界复制,长值是常数时间共享

-
-
-
-
10B · Cheetah
18.28 ns
-
10B · String
31.01 ns
-
23B · Cheetah
27.25 ns
-
23B · String
46.28 ns
-
24B · Cheetah
19.14 ns
-
24B · String
40.55 ns
-
1KiB · Cheetah
26.49 ns
-
1KiB · String
246.10 ns
-
-

前六条以 60 ns 为满刻度;1KiB 两条以 246.10 ns 为满刻度。精确值见右表。

-
-
- - - - - - - - -
payloadCheetah cloneString clone判断
10 B18.277 ns31.010 ns快约 41%
23 B27.245 ns46.283 ns快约 41%
24 B19.136 ns40.545 ns快约 53%
100 B23.262 ns69.200 ns快约 66%
1 KiB26.494 ns246.10 ns9.29× 快
-
-
可重复证据:长值 clone 在分配计数器下为 0 allocation,且 clone 前后 payload 指针一致。短值 clone 最多复制 23B;长值只增加 Arc<str> 的原子引用计数。
- -

构造与冻结:零拷贝入口已补齐,SSO 边界仍可观察

-
-
From<Arc<str>> · long
0 alloc

转换复用原 payload 指针;这是调用方已有共享字符串时的真实零拷贝入口。

-
1KiB freeze
1 / 2 alloc

exact-capacity 输入 1 次、1040B;spare-capacity 输入 2 次、2064B。写入侧仍为 O(n) 冻结。

-
-
- - - - - - - - -
borrowed inputCheetahString::fromString::from本机判断
23 B28.884 ns46.666 ns内联,快约 38%
24 B54.287 ns34.819 ns进入 Shared,慢约 56%
25 B55.754 ns40.688 ns慢约 37%
100 B73.848 ns70.509 ns近似持平
1 KiB295.22 ns295.64 ns近似持平
- -

Schema v3:确定性分配证据

-
- - - - - - - - -
操作allocation eventsallocated bytes契约
1KiB borrowed → Shared11040一次共享 backing 分配
1KiB owned exact → Shared11040冻结复制到最终 backing
1KiB owned spare → Shared22064收缩/复制成本显式可见
long Arc<str> adoption00payload pointer reused
Shared clone / char / short concat00三个热路径均有回归门禁
- -
RocketMQ 形状已接近持平。10,000 个 25B topic 插入的 median:CompactString 580.14 µs、String 614.94 µs、CheetahString 653.37 µs、Arc<str> 666.42 µs。Cheetah 比 String 慢约 6.3%,但两者 95% CI 重叠;24B 槽位消除了旧 32B 表示的密度劣势。随机 hash seed 与本机噪声仍使该结果只适合作为诊断,不作为发布硬门。
- -

搜索与 SIMD:代码路径保守,历史基线仅作方向性参考

-
-

memchr/memmem + Finder

空 needle 为 O(1),单字节走 memchr,多字节走 memmem;重复查询可复用预构建 Finder。该路径在 3.1 未改变,初始审计中 64KiB 末尾单字节诊断为 613 ns,而 str::find 为 36.5 µs。

-

实验 SSE2 默认关闭

初始诊断呈混合结果:16B equality 明显受益,但 starts_with 和部分中等长度 equality 退化。3.1 修复 Rust 1.95 编译边界但未把 SIMD 设为默认;这一决策与证据一致。

-
-

搜索与 SIMD 数值来自初始审计基线,不混入当前 95 分评分。启用 SIMD 前仍应按 CPU family、操作和长度校准,并保留 portable fallback。

-
-
- -
-
-
-
04 / MEMORY
-

内存布局:安全 24B 表示保留完整 23B SSO

私有的受约束长度枚举为三态表示提供安全 niche;64 位与 32 位布局快照都把 CheetahStringOption<CheetahString> 固定在 24B,未引入整数化指针。

-
-
-
-
-
CheetahString
24 B
-
Option<Cheetah>
24 B
-
String
24 B
-
Arc<str>
16 B
-
&str
16 B
-
-
-

容器级含义

100 万个元素只算对象槽位:Cheetah 与 String 都约 22.9 MiB。相对旧 32B 表示,Cheetah 每百万元素节省约 7.6 MiB;10,000 项的确定性证据为 240,000B,对照旧表示为 320,000B。

HashMap 中 (CheetahString, usize)(String, usize) 的 payload 均为 32B。这个结果同时保留 23B SSO、Option niche 与稳定指针 provenance。

-
-

来源:LAYOUT.mdtests/layout_snapshot.rs 与 schema-v3 allocation evidence;CI 在原生 i686 target 上运行 32 位布局测试。

-
-
- -
-
-
-
05 / SAFETY
-

安全:问题表示已退役,稳定 24B 路径通过 provenance 验证

3.1 不再公开旧 packed 模块;兼容 feature 名仅为空操作。当前 24B 表示使用 Safe Rust 的枚举 niche,稳定 unsafe 边界集中记录并由 Miri、审计和全特性测试共同约束。

-
- -
-
Rust tests
203/203

171 unit/integration + 32 doctests;all-features 全过。

-
Miri matrix
61 pass

lib 4、API 3、basic 47、bytes 7,覆盖三种 storage mode 与转换边界。

-
Supply chain
0 findings

74 个依赖;本地 advisory database 中无漏洞或 warning。

-
- -
P2

将 fuzz 从“可构建”提升为持续执行

Safety workflow 会编译两个稳定 fuzz target,但当前证据没有固定时长的自动 corpus 执行。字符编码和 bytes 转换边界适合增加 Linux sanitizer runner 与定时任务。

残余风险:输入空间
safety.yml
fuzz_targets/
-
P2

为时延回归准备固定硬件基线

布局与分配已是确定性硬门,但 Criterion 时延仍受本机频率、后台负载和 hash seed 影响。若要阻断时延回归,需要固定 runner、base/head 交错轮次和原始 artifact。

残余风险:性能漂移
performance.yml
-
P3

继续隔离 3.1 兼容 surface

旧 pattern dispatch 和 umbrella Error 为不升级大版本而保留,但内部查询已不再依赖公开 dispatch,并有下游 API 合约与 semver 基线。未来删除必须留到主版本。

残余风险:演进成本
API.md
- -
安全结论:旧 packed safe API 已从发布 surface 移除;experimental-packed 仅保留为 3.1 兼容 no-op feature。内部 unchecked helper 已改成真实 unsafe fn 边界,每个调用点必须给出局部证明;SAFETY.md 集中记录稳定不变量和 Miri 矩阵。
-
-
- -
-
-
-
06 / EVIDENCE
-

工程质量:证据链闭合,发布路径 fail-closed

3.1 将测试、文档、MSRV、Miri、供应链、API 兼容和确定性性能证据拆成五个固定 SHA 的 workflow。README、crate metadata 与实际门禁一致,发布验证先于 tag 和 publish。

-
- -
- - - - - - - - - - - - - - - -
验证结果事实判断
cargo test --all-featuresPASS203/203171 unit/integration + 32 doctests
cargo clippy --all-targets --all-features -- -D warningsPASS0 warnings现代工具链洁净
cargo fmt --all -- --checkPASSclean格式门禁正常
no_std + serde/bytes/simd matrixPASSstable + Rust 1.95功能组合可构建/测试
cargo packagePASS79 files · 394.3 KiB发布包自包含且排除未跟踪 docs
Miri matrixPASS61 tests三种表示与 API/bytes 边界通过
rustdoc -D warningsPASS22/22 documented;2/2 examplesdefault/no-default/all-features 均受控
Rust 1.95 packaged consumersPASSdefault + feature consumersMSRV 对发布包与 SIMD 成立
API compatibilityPASS*post-retirement baseline: 196 pass对 3.0.0 有 3 个已批准的实验安全移除
Python repository testsPASS24 testsworkflow 与证据 schema 自包含
cargo auditPASS0 vulnerabilities / 0 warnings无失维护的项目依赖
fuzz targetsPASS2 targets build编译有门;持续执行仍为改进项
- -

当前证据链的四个支点

-
-

五类 workflow 分责

CI、Safety、Performance、API Compatibility 与 Release 分离,第三方 Actions 固定到完整 commit SHA,职责与 README 声明一致。

.github/workflows/

-

发布顺序 fail-closed

版本输入经环境变量与格式校验;fmt、Clippy、test、package 和内容校验全部通过后,才创建 tag 并发布。

release.yml

-

确定性性能 schema v3

布局、分配次数、分配字节、Arc 指针复用与 10k 容器密度由机器可读证据和 Python verifier 共同验证。

PERFORMANCE.md

-

文档与元数据同源

3.1.0、Rust 1.95、feature surface、安全边界与性能承诺在 Cargo metadata、README 和根级专题文档中一致。

README.md · Cargo.toml

-
- -
工程结论:初始审计中的 MSRV、Miri、rustdoc、依赖、文档和发布顺序缺陷均已有自动门禁。当前主要工程缺口不再是“证据是否存在”,而是把 fuzz 动态执行与固定硬件时延基线提升到同等可重复级别。
-
-
- -
-
-
-
07 / ROADMAP
-

从 95 分继续收敛:强化连续证据,不扩大 3.1 surface

安全退役、24B 表示、MSRV、发布与 API 门禁已经落地。后续工作应围绕可重复测量和写入侧成本展开;兼容性清理不在 3.1 内破坏式推进。

-
-
-

持续执行 fuzz corpus

  • 在 Linux sanitizer runner 上定时执行两个稳定 target,而不只验证可编译。
  • 保存 crash artifact、seed corpus 与最小化输入,并把重现命令写入 Safety workflow。
  • 优先覆盖 UTF-8 边界、共享转换、substring range 与 clone/drop 交错。
-

建立固定硬件时延基线

  • 使用固定 CPU runner、锁定频率与 affinity,交错执行 base/head。
  • 上传 Criterion 原始 artifact、环境指纹与置信区间,不用单次 geomean 阻断发布。
  • 布局与 allocation schema v3 继续作为跨 runner 的确定性硬门。
-

优化写入侧长值路径

  • 对 upper/lower/replace/repeat 与 substring 分别测量中间 String 和 freeze copy。
  • 保持 From<Arc<str>> 零拷贝;为常见 exact/spare 容量分布建立真实 workload。
  • 只有在 API 语义清楚且 allocation contract 不退化时才引入专用 builder 快路径。
-

维持 3.1 兼容边界

  • 继续保留 deprecated pattern dispatch 与既有 Error 类型,不在 3.1 删除。
  • 内部实现保持依赖私有 classifier;通过 cargo-semver-checks 和 downstream contract 监控 surface。
  • 若未来允许主版本,再单独评估兼容 shim 与错误模型清理。
-
-
-
- -
-
-
-
08 / METHOD
-

方法、范围与可复现命令

复审基线为 300b313c3217a46a470c9b590ffc9e80584e9759,最终报告通过独立 PR 合入。报告把机器可重复的测试、布局、分配、MSRV 和 API 合约与本机 Criterion 诊断严格分开;评分不依赖一次性纳秒结果。

-
- -
-
环境

Windows NT 10.0.26200
x86_64-pc-windows-msvc
i7-11700K @ 3.60GHz
rustc/cargo 1.96.1
LLVM 22.1.2

-
仓库规模

15 src files / 2,326 lines
16 integration files / 1,764 lines
10 benchmarks / 1,934 lines
2 fuzz targets
5 workflows
3 normal deps at all-features

-
统计口径

Criterion 使用 median;95% CI 重叠时不作速度排名。代码行数不代表覆盖率,测试数量也不代替 property/fuzz coverage。评分扣分只对应仍可复现的残余风险。

-
- -
核心验证命令
- cargo fmt --all -- --check -cargo clippy --all-targets --all-features -- -D warnings -cargo test --all-features -cargo test --no-default-features --features serde,bytes -cargo check --no-default-features -RUSTDOCFLAGS="-D warnings" cargo doc --lib --all-features --no-deps -RUSTDOCFLAGS="-D warnings" cargo doc --lib --no-deps -cargo +1.95 check --lib --all-features -& scripts\check-msrv-package.ps1 -Msrv 1.95 -AllowDirty -cargo test --test allocation_contract --all-features -- --test-threads=1 -cargo test --test layout_snapshot --all-features -- --nocapture -cargo package --allow-dirty -python -m unittest discover -s scripts/tests -p "test_*.py" -v -
-
性能命令
- cargo bench --bench shared_backing -- __allocation_evidence_only__ --noplot 2>&1 | Tee-Object target/allocation-evidence.log -python scripts/verify-allocation-evidence.py target/allocation-evidence.log -cargo bench --bench comprehensive -- size_scaling --warm-up-time 0.5 --measurement-time 1 --sample-size 30 --noplot -cargo bench --bench mq_topic -- mq_topic_insert --warm-up-time 0.5 --measurement-time 1 --sample-size 30 --noplot -

allocation evidence 是 schema-v3 硬门;Criterion 运行期间存在桌面后台负载,未固定 governor/affinity,也未做 base/head 双向轮次。CI 重叠的差异按“近似持平”处理。

-
-
Miri / 供应链 / 受限验证
- cargo +nightly miri test --lib --no-default-features -cargo +nightly miri test --test api_contract --no-default-features -cargo +nightly miri test --test basic --no-default-features -cargo +nightly miri test --test bytes --features bytes -cargo audit --json -cargo +nightly fuzz build -

Miri 本地矩阵共 61 项通过。两个稳定 fuzz target 纳入编译门禁,但本轮不把“build pass”表述为动态 fuzz pass;cargo audit 基于本地更新后的 advisory database。

-
- -

关键证据索引

-
- - - - - - - - - - - - - -
主张一手证据
三态表示与 23B inlinerepr.rsinline.rs
24B provenance-safe layoutLAYOUT.mdlayout_snapshot.rs
Arc adoption / 构造 / 冻结construct.rsbuilder.rs
allocation schema v3allocation_contract.rsPERFORMANCE.md
memchr/memmem/Findersearch.rspattern.rs
MQ topic workloadmq_topic.rs
稳定 unsafe / retired featureSAFETY.mdfeature_contract.rs
3.1 API 与 error contractsAPI.mdapi_contract.rs
MSRV / feature 声明Cargo.tomlcheck-msrv-package.ps1
CI、安全、性能、API 与发布.github/workflows/
-
-
- -
-
-
Independent repository re-audit · generated 2026-08-12
CheetahString v3.1.0 · baseline 300b313
- -
-
-
- - - - diff --git a/scripts/tests/test_repository_contracts.py b/scripts/tests/test_repository_contracts.py index dec7ca2..aeb8fbf 100644 --- a/scripts/tests/test_repository_contracts.py +++ b/scripts/tests/test_repository_contracts.py @@ -121,6 +121,19 @@ def test_retired_score_governance_is_not_shipped(self) -> None: for path in retired: self.assertFalse((ROOT / path).exists(), path) + def test_generated_audit_artifacts_are_not_shipped(self) -> None: + retired = ( + "API.md", + "LAYOUT.md", + "PERFORMANCE.md", + "SAFETY.md", + "cheetah-string-architecture-performance-report.html", + ) + readme = read("README.md") + for path in retired: + self.assertFalse((ROOT / path).exists(), path) + self.assertNotIn(path, readme) + def test_docs_directory_is_not_tracked_or_packaged(self) -> None: tracked = subprocess.run( ["git", "ls-files", "docs"],