mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-10 15:16:56 +00:00
perf(capacity): tune default capacity settings, sync docs, and fix refresh/metrics correctness (#2336)
Co-authored-by: heihutu <heihutu@gmail.com> Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
@@ -62,32 +62,32 @@ pub const ENV_CAPACITY_STALL_TIMEOUT: &str = "RUSTFS_CAPACITY_STALL_TIMEOUT";
|
||||
// ============================================================================
|
||||
|
||||
/// Scheduled update interval in seconds
|
||||
/// Default: 300 seconds (5 minutes)
|
||||
pub const DEFAULT_SCHEDULED_UPDATE_INTERVAL_SECS: u64 = 300;
|
||||
/// Default: 120 seconds (2 minutes)
|
||||
pub const DEFAULT_SCHEDULED_UPDATE_INTERVAL_SECS: u64 = 120;
|
||||
|
||||
/// Write trigger delay in seconds
|
||||
/// Default: 10 seconds
|
||||
pub const DEFAULT_WRITE_TRIGGER_DELAY_SECS: u64 = 10;
|
||||
/// Default: 5 seconds
|
||||
pub const DEFAULT_WRITE_TRIGGER_DELAY_SECS: u64 = 5;
|
||||
|
||||
/// Write frequency threshold (writes per minute)
|
||||
/// Default: 10 writes/minute
|
||||
pub const DEFAULT_WRITE_FREQUENCY_THRESHOLD: usize = 10;
|
||||
/// Default: 5 writes/minute
|
||||
pub const DEFAULT_WRITE_FREQUENCY_THRESHOLD: usize = 5;
|
||||
|
||||
/// Fast update threshold in seconds
|
||||
/// Default: 60 seconds
|
||||
pub const DEFAULT_FAST_UPDATE_THRESHOLD_SECS: u64 = 60;
|
||||
/// Default: 30 seconds
|
||||
pub const DEFAULT_FAST_UPDATE_THRESHOLD_SECS: u64 = 30;
|
||||
|
||||
/// Maximum files threshold for sampling
|
||||
/// Default: 1,000,000 files
|
||||
pub const DEFAULT_MAX_FILES_THRESHOLD: usize = 1_000_000;
|
||||
/// Default: 200,000 files
|
||||
pub const DEFAULT_MAX_FILES_THRESHOLD: usize = 200_000;
|
||||
|
||||
/// Statistics timeout in seconds
|
||||
/// Default: 5 seconds
|
||||
pub const DEFAULT_STAT_TIMEOUT_SECS: u64 = 5;
|
||||
/// Default: 3 seconds
|
||||
pub const DEFAULT_STAT_TIMEOUT_SECS: u64 = 3;
|
||||
|
||||
/// Sampling rate (1 in every N files)
|
||||
/// Default: 100
|
||||
pub const DEFAULT_SAMPLE_RATE: usize = 100;
|
||||
/// Default: 200
|
||||
pub const DEFAULT_SAMPLE_RATE: usize = 200;
|
||||
|
||||
/// Follow symbolic links during capacity calculation
|
||||
/// Default: false (disabled for safety)
|
||||
@@ -102,16 +102,16 @@ pub const DEFAULT_CAPACITY_MAX_SYMLINK_DEPTH: u8 = 3;
|
||||
pub const DEFAULT_CAPACITY_ENABLE_DYNAMIC_TIMEOUT: bool = true;
|
||||
|
||||
/// Minimum capacity calculation timeout in seconds
|
||||
/// Default: 5 seconds
|
||||
pub const DEFAULT_CAPACITY_MIN_TIMEOUT_SECS: u64 = 5;
|
||||
/// Default: 2 seconds
|
||||
pub const DEFAULT_CAPACITY_MIN_TIMEOUT_SECS: u64 = 2;
|
||||
|
||||
/// Maximum capacity calculation timeout in seconds
|
||||
/// Default: 60 seconds
|
||||
pub const DEFAULT_CAPACITY_MAX_TIMEOUT_SECS: u64 = 60;
|
||||
/// Default: 15 seconds
|
||||
pub const DEFAULT_CAPACITY_MAX_TIMEOUT_SECS: u64 = 15;
|
||||
|
||||
/// Progress stall detection timeout in seconds
|
||||
/// Default: 1 second (no progress for 1 second = stall)
|
||||
pub const DEFAULT_CAPACITY_STALL_TIMEOUT_SECS: u64 = 1;
|
||||
/// Default: 20 seconds
|
||||
pub const DEFAULT_CAPACITY_STALL_TIMEOUT_SECS: u64 = 20;
|
||||
|
||||
// ============================================================================
|
||||
// Tests
|
||||
@@ -140,16 +140,16 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_default_values() {
|
||||
assert_eq!(DEFAULT_SCHEDULED_UPDATE_INTERVAL_SECS, 300);
|
||||
assert_eq!(DEFAULT_WRITE_TRIGGER_DELAY_SECS, 10);
|
||||
assert_eq!(DEFAULT_WRITE_FREQUENCY_THRESHOLD, 10);
|
||||
assert_eq!(DEFAULT_FAST_UPDATE_THRESHOLD_SECS, 60);
|
||||
assert_eq!(DEFAULT_MAX_FILES_THRESHOLD, 1_000_000);
|
||||
assert_eq!(DEFAULT_STAT_TIMEOUT_SECS, 5);
|
||||
assert_eq!(DEFAULT_SAMPLE_RATE, 100);
|
||||
assert_eq!(DEFAULT_SCHEDULED_UPDATE_INTERVAL_SECS, 120);
|
||||
assert_eq!(DEFAULT_WRITE_TRIGGER_DELAY_SECS, 5);
|
||||
assert_eq!(DEFAULT_WRITE_FREQUENCY_THRESHOLD, 5);
|
||||
assert_eq!(DEFAULT_FAST_UPDATE_THRESHOLD_SECS, 30);
|
||||
assert_eq!(DEFAULT_MAX_FILES_THRESHOLD, 200_000);
|
||||
assert_eq!(DEFAULT_STAT_TIMEOUT_SECS, 3);
|
||||
assert_eq!(DEFAULT_SAMPLE_RATE, 200);
|
||||
assert_eq!(DEFAULT_CAPACITY_MAX_SYMLINK_DEPTH, 3);
|
||||
assert_eq!(DEFAULT_CAPACITY_MIN_TIMEOUT_SECS, 5);
|
||||
assert_eq!(DEFAULT_CAPACITY_MAX_TIMEOUT_SECS, 60);
|
||||
assert_eq!(DEFAULT_CAPACITY_STALL_TIMEOUT_SECS, 1);
|
||||
assert_eq!(DEFAULT_CAPACITY_MIN_TIMEOUT_SECS, 2);
|
||||
assert_eq!(DEFAULT_CAPACITY_MAX_TIMEOUT_SECS, 15);
|
||||
assert_eq!(DEFAULT_CAPACITY_STALL_TIMEOUT_SECS, 20);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
// 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.
|
||||
|
||||
//! Capacity metrics recording helpers.
|
||||
|
||||
use metrics::{counter, gauge, histogram};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Record capacity cache hit.
|
||||
#[inline(always)]
|
||||
pub fn record_capacity_cache_hit() {
|
||||
counter!("rustfs.capacity.cache.hits").increment(1);
|
||||
}
|
||||
|
||||
/// Record capacity cache miss.
|
||||
#[inline(always)]
|
||||
pub fn record_capacity_cache_miss() {
|
||||
counter!("rustfs.capacity.cache.misses").increment(1);
|
||||
}
|
||||
|
||||
/// Record current capacity gauge.
|
||||
#[inline(always)]
|
||||
pub fn record_capacity_current_bytes(used_bytes: u64) {
|
||||
gauge!("rustfs.capacity.current").set(used_bytes as f64);
|
||||
}
|
||||
|
||||
/// Record capacity update completion.
|
||||
#[inline(always)]
|
||||
pub fn record_capacity_update_completed(source: &str, duration: Duration, used_bytes: u64, is_estimated: bool) {
|
||||
counter!("rustfs.capacity.update.total", "source" => source.to_string()).increment(1);
|
||||
histogram!("rustfs.capacity.update.duration.seconds", "source" => source.to_string()).record(duration.as_secs_f64());
|
||||
histogram!("rustfs.capacity.update.bytes", "source" => source.to_string()).record(used_bytes as f64);
|
||||
counter!("rustfs.capacity.update.estimated.total", "source" => source.to_string(), "estimated" => is_estimated.to_string())
|
||||
.increment(1);
|
||||
}
|
||||
|
||||
/// Record failed capacity update.
|
||||
#[inline(always)]
|
||||
pub fn record_capacity_update_failed(source: &str) {
|
||||
counter!("rustfs.capacity.update.failures", "source" => source.to_string()).increment(1);
|
||||
}
|
||||
|
||||
/// Record capacity write activity.
|
||||
#[inline(always)]
|
||||
pub fn record_capacity_write_operation(write_frequency: usize) {
|
||||
counter!("rustfs.capacity.write.operations").increment(1);
|
||||
gauge!("rustfs.capacity.write.frequency").set(write_frequency as f64);
|
||||
}
|
||||
|
||||
/// Record symlink accounting.
|
||||
#[inline(always)]
|
||||
pub fn record_capacity_symlink(size_bytes: u64) {
|
||||
counter!("rustfs.capacity.symlinks.encountered").increment(1);
|
||||
histogram!("rustfs.capacity.symlinks.size.bytes").record(size_bytes as f64);
|
||||
}
|
||||
|
||||
/// Record timeout fallback event.
|
||||
#[inline(always)]
|
||||
pub fn record_capacity_timeout_fallback() {
|
||||
counter!("rustfs.capacity.timeout.fallback").increment(1);
|
||||
}
|
||||
|
||||
/// Record stall detection event.
|
||||
#[inline(always)]
|
||||
pub fn record_capacity_stall_detected() {
|
||||
counter!("rustfs.capacity.timeout.stall").increment(1);
|
||||
}
|
||||
|
||||
/// Record dynamic timeout usage.
|
||||
#[inline(always)]
|
||||
pub fn record_capacity_dynamic_timeout(timeout: Duration) {
|
||||
counter!("rustfs.capacity.timeout.dynamic").increment(1);
|
||||
histogram!("rustfs.capacity.timeout.dynamic.seconds").record(timeout.as_secs_f64());
|
||||
}
|
||||
|
||||
/// Record scan sampling outcome.
|
||||
#[inline(always)]
|
||||
pub fn record_capacity_scan_sampling(sampled_count: usize, estimated: bool) {
|
||||
histogram!("rustfs.capacity.scan.sampled.count").record(sampled_count as f64);
|
||||
counter!("rustfs.capacity.scan.estimated.total", "estimated" => estimated.to_string()).increment(1);
|
||||
}
|
||||
@@ -52,6 +52,7 @@ pub mod adaptive_ttl;
|
||||
pub mod autotuner;
|
||||
pub mod backpressure_metrics;
|
||||
pub mod cache_config;
|
||||
pub mod capacity_metrics;
|
||||
pub mod collector;
|
||||
pub mod config;
|
||||
pub mod deadlock_metrics;
|
||||
@@ -71,6 +72,13 @@ pub use adaptive_ttl::{
|
||||
record_ttl_expiration,
|
||||
};
|
||||
|
||||
// Capacity metrics exports
|
||||
pub use capacity_metrics::{
|
||||
record_capacity_cache_hit, record_capacity_cache_miss, record_capacity_current_bytes, record_capacity_dynamic_timeout,
|
||||
record_capacity_scan_sampling, record_capacity_stall_detected, record_capacity_symlink, record_capacity_timeout_fallback,
|
||||
record_capacity_update_completed, record_capacity_update_failed, record_capacity_write_operation,
|
||||
};
|
||||
|
||||
// I/O metrics exports
|
||||
pub use io_metrics::{
|
||||
IoSchedulerStats, record_bandwidth_observation, record_buffer_size_adjustment, record_io_priority_decision,
|
||||
|
||||
Reference in New Issue
Block a user