chore: release v5.0.0#272
Conversation
8b69d29 to
22132a5
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
22132a5 to
9333d1d
Compare
537ad18 to
5fad0f0
Compare
There was a problem hiding this comment.
⚠️ Performance Alert ⚠️
Possible performance regression was detected for benchmark 'lsm-tree db_bench'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.15.
| Benchmark suite | Current: 1c24a37 | Previous: ce61479 | Ratio |
|---|---|---|---|
fillseq |
929652.2170850233 ops/sec (normalized) |
1203358.892593456 ops/sec (normalized) |
1.29 |
fillrandom |
485572.12090749916 ops/sec (normalized) |
684004.055959021 ops/sec (normalized) |
1.41 |
readrandom |
249420.72751907416 ops/sec (normalized) |
293185.8790669865 ops/sec (normalized) |
1.18 |
overwrite |
520188.67348067 ops/sec (normalized) |
651165.60047447 ops/sec (normalized) |
1.25 |
mergerandom |
396090.88280023885 ops/sec (normalized) |
466073.7463258474 ops/sec (normalized) |
1.18 |
This comment was automatically generated by workflow using github-action-benchmark.
CC: @polaz
1f6bceb to
ca002fa
Compare
4d67a8e to
6cb13ca
Compare
…#133 phase 2) (#310) ## Summary Foundation layer for `O_DIRECT` cache-bypass I/O. Two pieces: 1. **`AlignedBuf`** (`src/fs/aligned_buf.rs`) — heap-allocated byte buffer with caller-specified alignment. `Vec<u8>` defaults to `align_of::<u8>() = 1`, which violates `O_DIRECT`'s typical 4 KiB userspace-buffer alignment (EINVAL on unaligned write/read). `AlignedBuf` allocates via `Layout::from_size_align`, rounds capacity up to a multiple of alignment, and exposes a `Vec`-like surface (`len`/`capacity`/`as_slice`/`as_capacity_mut`/`set_len`/`clear`) + raw ptr accessors for kernel handoff. 2. **`FsOpenOptions::direct_io`** — new `bool` field + builder method. On Linux/Android (arches where `asm-generic/fcntl.h`'s `O_DIRECT = 0o40000` is the authoritative value: x86, x86_64, aarch64, riscv32/64, loongarch64, s390x) the flag becomes a `custom_flags(O_DIRECT)` on the std `OpenOptions` builder, in both `StdFs::open` and `IoUringFs::open`. `O_DIRECT` is declared as a named constant rather than pulling in `libc` — matches the existing `EXDEV` / `flock` pattern in `std_fs.rs`. Architectures with a divergent `O_DIRECT` bit (arm `0o200000`, mips `0o100000`, parisc, sparc) are not gated on purpose: emitting the wrong bit silently would be worse than honouring the documented "`direct_io` may be ignored" contract. macOS / Windows / other Unix targets fall through to a cached open for the same reason — `F_NOCACHE` / `FILE_FLAG_NO_BUFFERING` each need their own opt-in plumbing. ## Design choices (explicit so review does not re-raise) - **`FsOpenOptions` is `#[non_exhaustive]`.** This is breaking (struct-literal callers + exhaustive pattern matches stop compiling) but only relative to the same release that introduces the new `direct_io` field — which is already breaking for the same callers. Bundling both changes in one release confines the break to a single semver-major bump (v5.0.0, queued in PR #272) and lets every future field land as semver-minor. Builder methods (`.read()`, `.write()`, … `.direct_io()`) cover every field, so non-struct-literal callers are unaffected. - **`fs::direct_io` submodule IS gated behind `#[cfg(feature = "std")]`.** It uses `std::fs::OpenOptions` and is therefore std-only. The gate is the first concrete step toward honestly feature-gating the std backend per crate policy. However, it does NOT by itself unblock a `no_std + alloc` build: the rest of the `fs::*` backend — the `Fs`/`FsFile` trait *definitions* and all impls (`std_fs`, `io_uring_fs`, even `MemFs`) — still references `std::io::{Read, Write, Seek}` + `std::path::Path` directly, and those have no `core::*` equivalents. Porting the trait surface off `std::io` / `std::path` is a structural prerequisite tracked as a separate prerequisite issue (#311), itself part of the no-std migration epic (#274). The `no-std-check` CI job is `continue-on-error` for exactly this reason — net error count is not changed by this PR. ## What's NOT in this PR The Tree-level `Config::direct_io` knob and compaction-writer integration are deferred to a follow-up. The current SST writer uses `Vec<u8>` buffers and unaligned block sizes; wiring `direct_io` into `Config` without an alignment-aware writer would EINVAL on first write. Foundation lands here so the writer refactor can build on it. ## Test plan - [x] 12 unit tests for `AlignedBuf` (alignment verification, capacity rounding, zero init, rejects non-power-of-two / excessive alignment, zero-capacity dangling sentinel, `set_len` growth + panic, `clear`, `as_capacity_mut` writes, `Send`/`Sync` compile check, pointer stability) - [x] `fs_open_options_default` + `fs_open_options_builders` updated to cover the new field - [x] Full nextest suite: 1542 tests pass (1 slow), 6 skipped - [x] cargo clippy all-features all-targets with -D warnings — clean - [x] Doctest for `AlignedBuf::new_zeroed` example compiles and passes ## Related - #311 — port `Fs`/`FsFile` traits off `std::io` + `std::path` (prerequisite for the rest of `fs::*` to become honestly feature-gateable) - #274 — no-std migration epic (parent) - #272 — release-plz v5.0.0 (semver-major bump that ships the breaking changes here) Part of #133
8f95b2a to
310edff
Compare
a270353 to
40c8fd6
Compare
f303ee5 to
e5ddeca
Compare
Hold — V5 release batch coordinationThis release-plz PR is held in open state pending completion of V5 format batch. RationalePer Q-cycle release strategy decision: V5 will bundle several format-changing features so post-V5 manifests/blocks have a single coherent version step (no V5→V6 rapid succession that would penalize users with chained format migrations). V5 batch contents (in addition to what's already in this PR)
Estimated total wall time: ~2-3 weeks from now. Already in this PR (will ship as part of V5)
Action plan
If batch hits a blockerPer-issue independence allows partial V5 ship — if e.g. #297 unexpectedly blocks, V5 ships with #352 + #298 + #224 only; #297 follows in V5.x (additive) or V6 if it requires format break. Marketing pull-quote (target)"V5: production-grade integrity stack — BuRR filter, Page ECC, AAD encryption, per-KV protection, block-level seqno bounds for CDC, manifest hardening, runtime-toggleable everything with zero-downtime migration via compaction." When this resolves
|
## Summary V5-1 of the V5 release batch — foundation for live-toggleable configuration that downstream V5 features (#297 manifest hardening, #298 per-KV protection, #224 scan_since_seqno) build on. Caller updates settings via `Tree::update_runtime_config`; subsequent write paths load the new snapshot lockless. Existing on-disk data stays in its original format and reads transparently via per-block self-description. Compaction acts as the live migration mechanism — source blocks rewritten per the current snapshot over subsequent cycles, all data converges without stop-the-world coordination. Closes #352. ## Layered tier separation (no_std-aware) | Module | Tier | Why | |--------|------|-----| | `runtime_config::types` | `alloc` (compiles on no_std + alloc) | Pure data: `RuntimeConfig` + `ChecksumAlgorithm`. Reachable from no_std consumers (block decoders, format constants). | | `runtime_config::handle` | std-bound (`#[cfg(feature = "std")]`) | `ArcSwap`-based snapshot. `load()` = single atomic load; `update(fn)` = clone, mutate, atomic swap. | ## Public API ```rust impl Tree { pub fn runtime_config(&self) -> Arc<RuntimeConfig>; pub fn update_runtime_config<F: FnOnce(&mut RuntimeConfig)>(&self, mutator: F); } ``` ## ChecksumAlgorithm Used by downstream V5 features (#297, #298, #300) for block-level and per-KV checksums. Stable `wire_tag()` / `from_wire_tag()` for on-disk self-description so each block can dispatch verify per its own recorded algorithm. | Variant | Bytes | Speed | Notes | |---------|-------|-------|-------| | `Xxh3_64` (default) | 8 | ~50-100 GB/s SIMD | Default — matches crate-wide XXH3 convention | | `Xxh3Low32` | 4 | same as `Xxh3_64` | Per-entry use case where space matters | | `Crc32c` | 4 | ~30 GB/s HW | Mathematically-proven burst-error detection | ## Tests - **10 unit tests** in `runtime_config::types` + `runtime_config::handle`: - digest sizes, wire-tag roundtrip, atomic swap visibility - snapshot held during update is unchanged (compaction-as-migration prerequisite) - concurrent-reads-during-update consistent state (no torn reads under stress) - multiple back-to-back updates: final-state observable - **4 integration tests** in `tests/runtime_config_integration.rs`: - Tree starts at default - update visible on next load - snapshot outlives update with pre-update state - runtime config resets to default on reopen (by design — caller re-applies) **Workspace: 1664/1664 tests pass** (+24 new vs prior baseline). Lints clean across all-features lib + tests. Doc tests pass (43). ## Test plan - [x] strict lints clean across all-features lib + tests - [x] full nextest workspace: 1664/1664 pass - [x] doc tests pass (43) - [x] runtime_config unit tests pass (10/10) - [x] runtime_config integration tests pass (4/4) - [x] concurrent torn-read stress test passes (8 readers × 5000 reads + writer) ## Dependency `arc-swap = "1.9"` (std-bound; the `experimental-thread-local` no_std mode is out of scope for now). Handle behind `#[cfg(feature = "std")]`; future no_std consumers can use `spin::RwLock<RuntimeConfig>` as alternative documented in code. ## V5 batch coordination This is V5-1. After merge, V5-2 (#297), V5-3 (#298), V5-4 (#224) can land in parallel worktrees consuming this foundation. release-plz PR #272 stays held until full V5 batch lands — then v5.0.0 ships with the complete integrity stack as one coherent release. See #215 ROADMAP for full V5 plan. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added runtime-configurable checksum algorithms for block and key-value integrity checks. * New lockless, live configuration API to update and read runtime settings without restarts. * Configuration changes are isolated per tree session and reset to defaults upon tree reopen. * **Tests** * Added integration and unit tests validating runtime configuration updates, atomic snapshot semantics, and persistence behavior. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/structured-world/coordinode-lsm-tree/pull/355?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
e5ddeca to
5e00028
Compare
5e00028 to
59e4a4f
Compare
🤖 New release
coordinode-lsm-tree: 4.5.0 -> 5.0.0Changelog
This PR was generated with release-plz.