mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-28 16:07:05 +00:00
59fd318192
* feat(mimalloc): add arena diagnostics and configuration Based on mimalloc maintainer feedback (microsoft/mimalloc#1372), add diagnostics to check mimalloc arena configuration at runtime. Changes: - Add rustfs-mimalloc-sys to workspace dependencies - Add log_mimalloc_diagnostics() function to check: - arena_max_object_size - pagemap_commit status - mimalloc version - Add memory_observability module with mimalloc diagnostics This helps diagnose why allocations might be going outside arenas, which is the suspected root cause of futex contention. Ref: rustfs/backlog#2005 Ref: microsoft/mimalloc#1372 Co-Authored-By: heihutu <heihutu@gmail.com> * perf(ecstore): add Vec<u8> buffer pool for EC operations Add a general-purpose buffer pool to reduce Vec<u8> allocations in hot paths like EC encoding/decoding. Changes: - Add BufferPool struct in crates/ecstore/src/erasure/codec/buffer_pool.rs - Thread-safe pool with capacity-based bucketing (power-of-two) - Global EC_BUFFER_POOL instance with 16 buffers per bucket - Add buffer_pool module to codec/mod.rs Expected impact: - Reduce heap allocations in EC encode/decode paths - Avoid memzero overhead (proven 4.8% CPU saving in ShardBufferPool) - Reduce mimalloc lock contention Note: Main bottleneck remains mimalloc internal synchronization (futex 98.64% time). Buffer pool provides modest improvement (+2-5%). Ref: rustfs/backlog#2005 Co-Authored-By: heihutu <heihutu@gmail.com> * style: apply cargo fmt to buffer pool and related files Co-Authored-By: heihutu <heihutu@gmail.com> * fix(ecstore): add #[allow(dead_code)] to buffer pool The BufferPool infrastructure is ready but not yet integrated into the EC hot paths. Add #[allow(dead_code)] with clear documentation about integration status. Co-Authored-By: heihutu <heihutu@gmail.com> * perf(ecstore): integrate BufferPool into bitrot verify path Replace vec![0; shard_size] with get_ec_buffer() in the bitrot verification hot path to reduce heap allocations and avoid memzero. Co-Authored-By: heihutu <heihutu@gmail.com> * style: apply cargo fmt to buffer pool and bitrot changes Co-Authored-By: heihutu <heihutu@gmail.com> * refactor(ecstore): clean up buffer pool code - Remove unnecessary #[allow(dead_code)] attributes - Update module documentation to reflect current integration status - Simplify code structure Co-Authored-By: heihutu <heihutu@gmail.com> * perf(runtime): cap default worker threads at 16 Testing showed 16 worker threads outperforms 32+ for 1KiB PUT workloads due to reduced mimalloc lock contention. A/B test results (testing 4-node cluster, c=64): - worker_threads=32: 740 obj/s (baseline) - worker_threads=16: 785 obj/s (+6.1%) The default was detect_cores() which returned 32 on our testing nodes. Cap at 16 for optimal small-object performance. Ref: rustfs/backlog#2005 Co-Authored-By: heihutu <heihutu@gmail.com> * style: apply cargo fmt to buffer pool and runtime changes Co-Authored-By: heihutu <heihutu@gmail.com> * fix(ecstore): remove unused BufferPool::new() function The new() function was never used since EC_BUFFER_POOL initializes directly with with_limits(16). Co-Authored-By: heihutu <heihutu@gmail.com> * fix(ecstore): update buffer_pool tests to use with_limits Replace BufferPool::new() with BufferPool::with_limits(16) in tests since new() was removed in favor of with_limits(). Co-Authored-By: heihutu <heihutu@gmail.com> * perf(ecstore): optimize opts.clone() and FileInfo clone patterns ## Changes 1. ObjectOptions helper methods: - add as_commit_opts(): creates commit options with no_lock=true, metadata_cache_safe=false, include_part_checksums=true - add as_read_opts(): creates read options with include_part_checksums=true - add with_no_lock(): creates options with modified no_lock field 2. Replace opts.clone() in hot paths: - commit_opts = opts.as_commit_opts() (was 4-line manual clone) - read_opts = opts.as_read_opts() (was 2-line manual clone) 3. Optimize FileInfo clone in rename path: - avoid double clone: clone once and modify erasure.index in place - pass &file_info reference to rename_data_borrowed_with_fence ## A/B Results (4-node cluster, c=64) | Size | main | optimized | Change | |------|------|-----------|--------| | 1KiB | 892 obj/s | 920-976 obj/s | +3%~+9% | | 4KiB | 957 obj/s | 903 obj/s | -5.7% | | 16KiB | 922 obj/s | 855 obj/s | -7.3% | Note: 1KiB improvement is consistent. 4KiB/16KiB variance likely due to test noise; needs more rounds to confirm. Ref: rustfs/backlog#2005 Co-Authored-By: heihutu <heihutu@gmail.com> * perf(ecstore): add BytesMut buffer pool to EC encoding path Pre-allocate a Vec<BytesMut> pool in the EC encoding loop to avoid repeated heap allocations for ingest buffers. Changes: - Pre-allocate buffer pool with capacity 4 - Reuse buffers from pool after encoding - Return buffers to pool when capacity is sufficient Expected impact: +10-20% in EC encoding path by reducing BytesMut allocation overhead. Ref: rustfs/backlog#2005 Co-Authored-By: heihutu <heihutu@gmail.com> --------- Co-authored-by: hector <hetor@rustfs.com> Co-authored-by: heihutu <heihutu@gmail.com>
300 lines
11 KiB
TOML
300 lines
11 KiB
TOML
# Copyright 2024 RustFS Team
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
[package]
|
|
name = "rustfs-ecstore"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
license.workspace = true
|
|
repository.workspace = true
|
|
rust-version.workspace = true
|
|
homepage.workspace = true
|
|
description = "Erasure coding storage backend for RustFS, providing efficient data storage and retrieval with redundancy."
|
|
keywords = ["erasure-coding", "storage", "rustfs", "Minio", "solomon"]
|
|
categories = ["web-programming", "development-tools", "filesystem"]
|
|
documentation = "https://docs.rs/rustfs-ecstore/latest/rustfs_ecstore/"
|
|
|
|
|
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
[lints]
|
|
workspace = true
|
|
|
|
[features]
|
|
default = []
|
|
# Compiles the controlled list-objects namespace-journal chaos injector into a
|
|
# production binary (it is always available to tests). Off by default so the
|
|
# RUSTFS_LIST_OBJECTS_NAMESPACE_JOURNAL_CHAOS_* env vars cannot rewrite journal
|
|
# state in a stock build (backlog#1832).
|
|
list-chaos = []
|
|
rio-v2 = ["dep:rustfs-rio-v2"]
|
|
hotpath = [
|
|
"hotpath/hotpath",
|
|
"hotpath/tokio",
|
|
"hotpath/futures",
|
|
"hotpath/async-channel",
|
|
"hotpath/parking_lot",
|
|
"hotpath/reqwest-0-13",
|
|
"rustfs-checksums/hotpath",
|
|
"rustfs-common/hotpath",
|
|
"rustfs-concurrency/hotpath",
|
|
"rustfs-config/hotpath",
|
|
"rustfs-credentials/hotpath",
|
|
"rustfs-data-usage/hotpath",
|
|
"rustfs-filemeta/hotpath",
|
|
"rustfs-io-metrics/hotpath",
|
|
"rustfs-lifecycle/hotpath",
|
|
"rustfs-lock/hotpath",
|
|
"rustfs-madmin/hotpath",
|
|
"rustfs-object-capacity/hotpath",
|
|
"rustfs-policy/hotpath",
|
|
"rustfs-protos/hotpath",
|
|
"rustfs-replication/hotpath",
|
|
"rustfs-rio/hotpath",
|
|
"rustfs-rio-v2?/hotpath",
|
|
"rustfs-s3-types/hotpath",
|
|
"rustfs-signer/hotpath",
|
|
"rustfs-storage-api/hotpath",
|
|
"rustfs-tls-runtime/hotpath",
|
|
"rustfs-utils/hotpath",
|
|
"rustfs-crypto/hotpath",
|
|
]
|
|
hotpath-alloc = [
|
|
"hotpath",
|
|
"hotpath/hotpath-alloc",
|
|
"rustfs-checksums/hotpath-alloc",
|
|
"rustfs-common/hotpath-alloc",
|
|
"rustfs-concurrency/hotpath-alloc",
|
|
"rustfs-config/hotpath-alloc",
|
|
"rustfs-credentials/hotpath-alloc",
|
|
"rustfs-data-usage/hotpath-alloc",
|
|
"rustfs-filemeta/hotpath-alloc",
|
|
"rustfs-io-metrics/hotpath-alloc",
|
|
"rustfs-lifecycle/hotpath-alloc",
|
|
"rustfs-lock/hotpath-alloc",
|
|
"rustfs-madmin/hotpath-alloc",
|
|
"rustfs-object-capacity/hotpath-alloc",
|
|
"rustfs-policy/hotpath-alloc",
|
|
"rustfs-protos/hotpath-alloc",
|
|
"rustfs-replication/hotpath-alloc",
|
|
"rustfs-rio/hotpath-alloc",
|
|
"rustfs-rio-v2?/hotpath-alloc",
|
|
"rustfs-s3-types/hotpath-alloc",
|
|
"rustfs-signer/hotpath-alloc",
|
|
"rustfs-storage-api/hotpath-alloc",
|
|
"rustfs-tls-runtime/hotpath-alloc",
|
|
"rustfs-utils/hotpath-alloc",
|
|
"rustfs-crypto/hotpath-alloc",
|
|
]
|
|
hotpath-cpu = [
|
|
"hotpath",
|
|
"hotpath/hotpath-cpu",
|
|
"rustfs-checksums/hotpath-cpu",
|
|
"rustfs-common/hotpath-cpu",
|
|
"rustfs-concurrency/hotpath-cpu",
|
|
"rustfs-config/hotpath-cpu",
|
|
"rustfs-credentials/hotpath-cpu",
|
|
"rustfs-data-usage/hotpath-cpu",
|
|
"rustfs-filemeta/hotpath-cpu",
|
|
"rustfs-io-metrics/hotpath-cpu",
|
|
"rustfs-lifecycle/hotpath-cpu",
|
|
"rustfs-lock/hotpath-cpu",
|
|
"rustfs-madmin/hotpath-cpu",
|
|
"rustfs-object-capacity/hotpath-cpu",
|
|
"rustfs-policy/hotpath-cpu",
|
|
"rustfs-protos/hotpath-cpu",
|
|
"rustfs-replication/hotpath-cpu",
|
|
"rustfs-rio/hotpath-cpu",
|
|
"rustfs-rio-v2?/hotpath-cpu",
|
|
"rustfs-s3-types/hotpath-cpu",
|
|
"rustfs-signer/hotpath-cpu",
|
|
"rustfs-storage-api/hotpath-cpu",
|
|
"rustfs-tls-runtime/hotpath-cpu",
|
|
"rustfs-utils/hotpath-cpu",
|
|
"rustfs-crypto/hotpath-cpu",
|
|
]
|
|
# Exposes shared lifecycle/tier test utilities (MockWarmBackend, fault
|
|
# injection, xl.meta transition assertions) via `api::tier::test_util`.
|
|
# Enable only from `[dev-dependencies]` (rustfs/backlog#1148 ilm-6).
|
|
test-util = []
|
|
|
|
[dependencies]
|
|
starshard = { workspace = true }
|
|
hotpath.workspace = true
|
|
rustfs-filemeta.workspace = true
|
|
rustfs-utils = { workspace = true, features = ["full"] }
|
|
rustfs-rio.workspace = true
|
|
rustfs-rio-v2 = { workspace = true, optional = true }
|
|
rustfs-signer.workspace = true
|
|
rustfs-storage-api.workspace = true
|
|
rustfs-tls-runtime.workspace = true
|
|
rustfs-checksums.workspace = true
|
|
rustfs-config = { workspace = true, features = ["notify", "audit", "server-config-model"] }
|
|
rustfs-concurrency.workspace = true
|
|
rustfs-credentials = { workspace = true }
|
|
rustfs-common.workspace = true
|
|
rustfs-policy.workspace = true
|
|
rustfs-protos.workspace = true
|
|
rustfs-replication.workspace = true
|
|
rustfs-lifecycle.workspace = true
|
|
rustfs-s3-types = { workspace = true }
|
|
rustfs-data-usage.workspace = true
|
|
rustfs-object-capacity.workspace = true
|
|
rustfs-object-data-cache = { workspace = true, features = ["runtime-memory"] }
|
|
arc-swap.workspace = true
|
|
async-trait.workspace = true
|
|
bytes = { workspace = true, features = ["serde"] }
|
|
byteorder = { workspace = true }
|
|
chrono = { workspace = true, features = ["serde"] }
|
|
jiff = { workspace = true, features = ["serde"] }
|
|
glob = { workspace = true }
|
|
thiserror.workspace = true
|
|
flatbuffers.workspace = true
|
|
futures.workspace = true
|
|
futures-util.workspace = true
|
|
tracing.workspace = true
|
|
tracing-opentelemetry.workspace = true
|
|
serde = { workspace = true, features = ["derive"] }
|
|
time = { workspace = true, features = ["parsing", "formatting", "macros", "serde"] }
|
|
bytesize.workspace = true
|
|
serde_json = { workspace = true, features = ["raw_value"] }
|
|
quick-xml = { workspace = true, features = ["serialize", "async-tokio"] }
|
|
s3s = { workspace = true, features = ["minio"] }
|
|
http.workspace = true
|
|
opentelemetry.workspace = true
|
|
http-body = { workspace = true }
|
|
http-body-util.workspace = true
|
|
url.workspace = true
|
|
uuid = { workspace = true, features = ["v4", "fast-rng", "serde", "macro-diagnostics"] }
|
|
reed-solomon-erasure = { workspace = true, features = ["simd-accel"] }
|
|
reed-solomon-simd = { workspace = true }
|
|
lazy_static.workspace = true
|
|
moka = { workspace = true, features = ["future"] }
|
|
rustfs-lock.workspace = true
|
|
rustfs-io-metrics.workspace = true
|
|
regex = { workspace = true }
|
|
path-absolutize = { workspace = true }
|
|
rmp.workspace = true
|
|
rmp-serde.workspace = true
|
|
tokio-util = { workspace = true, features = ["io", "compat"] }
|
|
tokio-stream = { workspace = true, features = ["sync"] }
|
|
base64 = { workspace = true }
|
|
hmac = { workspace = true }
|
|
sha1 = { workspace = true }
|
|
sha2 = { workspace = true }
|
|
hex-simd = { workspace = true }
|
|
tempfile.workspace = true
|
|
hyper = { workspace = true, features = ["http2", "http1", "server"] }
|
|
hyper-util = { workspace = true, features = ["tokio", "server-auto", "server-graceful", "tracing"] }
|
|
hyper-rustls = { workspace = true, default-features = false, features = ["native-tokio", "http1", "tls12", "logging", "http2", "aws-lc-rs"] }
|
|
hostname.workspace = true
|
|
rustls = { workspace = true, default-features = false, features = ["aws-lc-rs", "logging", "tls12", "prefer-post-quantum", "std"] }
|
|
rustls-pki-types.workspace = true
|
|
tokio = { workspace = true, features = ["io-util", "sync", "signal", "fs", "rt-multi-thread"] }
|
|
tonic = { workspace = true, features = ["gzip", "deflate"] }
|
|
xxhash-rust = { workspace = true, features = ["xxh64", "xxh3"] }
|
|
tower = { workspace = true, features = ["timeout"] }
|
|
async-channel.workspace = true
|
|
enumset = { workspace = true }
|
|
num_cpus = { workspace = true }
|
|
rand = { workspace = true, features = ["serde"] }
|
|
pin-project-lite.workspace = true
|
|
md-5.workspace = true
|
|
memmap2 = { workspace = true }
|
|
libc.workspace = true
|
|
# "process" adds getrlimit for the io_uring fd-cache RLIMIT_NOFILE gate
|
|
# (backlog#1178); "fs" comes from the workspace default.
|
|
rustix = { workspace = true, features = ["process", "fs"] }
|
|
rustfs-madmin.workspace = true
|
|
reqwest = { workspace = true }
|
|
aws-sdk-s3 = { workspace = true, default-features = false, features = ["sigv4a", "default-https-client", "rt-tokio"] }
|
|
urlencoding = { workspace = true }
|
|
smallvec = { workspace = true, features = ["serde"] }
|
|
shadow-rs = { workspace = true, default-features = false }
|
|
async-recursion.workspace = true
|
|
aws-credential-types = { workspace = true }
|
|
aws-smithy-types = { workspace = true }
|
|
aws-smithy-runtime-api = { workspace = true, features = ["http-1x"] }
|
|
parking_lot = { workspace = true }
|
|
base64-simd.workspace = true
|
|
serde_urlencoded.workspace = true
|
|
google-cloud-storage = { workspace = true }
|
|
google-cloud-auth = { workspace = true }
|
|
faster-hex = { workspace = true }
|
|
ratelimit = { workspace = true }
|
|
aws-smithy-http-client = { workspace = true, default-features = false, features = ["rustls-aws-lc"] }
|
|
|
|
# Observability and Metrics
|
|
metrics = { workspace = true }
|
|
|
|
# Runtime-probed io_uring read backend (backlog#1104). Linux-only, from
|
|
# crates.io. The guard scripts/check_no_tokio_io_uring.sh allows an explicit
|
|
# io-uring integration; only the tokio "io-uring" runtime feature is banned.
|
|
[target.'cfg(target_os = "linux")'.dependencies]
|
|
rustfs-uring = "0.2.1"
|
|
|
|
[target.'cfg(windows)'.dependencies]
|
|
winapi-util.workspace = true
|
|
windows-sys = { workspace = true, features = [
|
|
"Wdk_Foundation",
|
|
"Wdk_Storage_FileSystem",
|
|
"Win32_Foundation",
|
|
"Win32_Security",
|
|
"Win32_Storage_FileSystem",
|
|
"Win32_System_IO",
|
|
"Win32_System_SystemServices",
|
|
"Win32_System_WindowsProgramming",
|
|
] }
|
|
|
|
[target.'cfg(windows)'.dev-dependencies]
|
|
windows-sys = { workspace = true, features = ["Win32_System_Ioctl"] }
|
|
|
|
[dev-dependencies]
|
|
tokio = { workspace = true, features = ["rt-multi-thread", "macros", "test-util", "fs"] }
|
|
criterion = { workspace = true, features = ["html_reports"] }
|
|
temp-env = { workspace = true, features = ["async_closure"] }
|
|
tracing-subscriber = { workspace = true, features = ["json", "env-filter", "time"] }
|
|
# Only for `pin_callsite_interest_for_test`, which registers a `NoSubscriber`
|
|
# dispatcher to keep tracing's process-global callsite-interest cache honest.
|
|
tracing-core = { workspace = true }
|
|
serial_test = { workspace = true }
|
|
metrics-util = { workspace = true, features = ["debugging"] }
|
|
opentelemetry_sdk = { workspace = true, features = ["rt-tokio"] }
|
|
proptest = "1"
|
|
rcgen.workspace = true
|
|
insta = { workspace = true, features = ["yaml", "json"] }
|
|
rustfs-crypto = { workspace = true }
|
|
tonic-prost = { workspace = true }
|
|
|
|
[build-dependencies]
|
|
shadow-rs = { workspace = true, default-features = false, features = ["build", "metadata"] }
|
|
|
|
[[bench]]
|
|
name = "erasure_benchmark"
|
|
harness = false
|
|
|
|
[[bench]]
|
|
name = "comparison_benchmark"
|
|
harness = false
|
|
|
|
[[bench]]
|
|
name = "rename_data_meta_benchmark"
|
|
harness = false
|
|
|
|
[[bench]]
|
|
name = "single_block_non_inline_benchmark"
|
|
harness = false
|
|
|
|
[lib]
|
|
doctest = false
|