mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-18 18:46:17 +00:00
remove unlinked file (#1258)
This commit is contained in:
@@ -1,325 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Benchmarks comparing fast lock vs old lock performance
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code)] // Temporarily disable benchmark tests
|
||||
mod benchmarks {
|
||||
use super::super::*;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio::task;
|
||||
|
||||
/// Benchmark single-threaded lock operations
|
||||
#[tokio::test]
|
||||
async fn bench_single_threaded_fast_locks() {
|
||||
let manager = Arc::new(FastObjectLockManager::new());
|
||||
let iterations = 10000;
|
||||
|
||||
// Warm up
|
||||
for i in 0..100 {
|
||||
let _guard = manager
|
||||
.acquire_write_lock("bucket", &format!("warm_{}", i), "owner")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// Benchmark write locks
|
||||
let start = Instant::now();
|
||||
for i in 0..iterations {
|
||||
let _guard = manager
|
||||
.acquire_write_lock("bucket", &format!("object_{}", i), "owner")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
let duration = start.elapsed();
|
||||
|
||||
println!("Fast locks: {} write locks in {:?}", iterations, duration);
|
||||
println!("Average: {:?} per lock", duration / iterations);
|
||||
|
||||
let metrics = manager.get_metrics();
|
||||
println!("Fast path rate: {:.2}%", metrics.shard_metrics.fast_path_rate() * 100.0);
|
||||
|
||||
// Should be much faster than old implementation
|
||||
assert!(duration.as_millis() < 1000, "Should complete 10k locks in <1s");
|
||||
assert!(metrics.shard_metrics.fast_path_rate() > 0.95, "Should have >95% fast path rate");
|
||||
}
|
||||
|
||||
/// Benchmark concurrent lock operations
|
||||
#[tokio::test]
|
||||
async fn bench_concurrent_fast_locks() {
|
||||
let manager = Arc::new(FastObjectLockManager::new());
|
||||
let concurrent_tasks = 100;
|
||||
let iterations_per_task = 100;
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let mut handles = Vec::new();
|
||||
for task_id in 0..concurrent_tasks {
|
||||
let manager_clone = manager.clone();
|
||||
let handle = task::spawn(async move {
|
||||
for i in 0..iterations_per_task {
|
||||
let object_name = format!("obj_{}_{}", task_id, i);
|
||||
let _guard = manager_clone
|
||||
.acquire_write_lock("bucket", &object_name, &format!("owner_{}", task_id))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Simulate some work
|
||||
tokio::task::yield_now().await;
|
||||
}
|
||||
});
|
||||
handles.push(handle);
|
||||
}
|
||||
|
||||
// Wait for all tasks
|
||||
for handle in handles {
|
||||
handle.await.unwrap();
|
||||
}
|
||||
|
||||
let duration = start.elapsed();
|
||||
let total_ops = concurrent_tasks * iterations_per_task;
|
||||
|
||||
println!("Concurrent fast locks: {} operations across {} tasks in {:?}",
|
||||
total_ops, concurrent_tasks, duration);
|
||||
println!("Throughput: {:.2} ops/sec", total_ops as f64 / duration.as_secs_f64());
|
||||
|
||||
let metrics = manager.get_metrics();
|
||||
println!("Fast path rate: {:.2}%", metrics.shard_metrics.fast_path_rate() * 100.0);
|
||||
println!("Contention events: {}", metrics.shard_metrics.contention_events);
|
||||
|
||||
// Should maintain high throughput even with concurrency
|
||||
assert!(duration.as_millis() < 5000, "Should complete concurrent ops in <5s");
|
||||
}
|
||||
|
||||
/// Benchmark contended lock operations
|
||||
#[tokio::test]
|
||||
async fn bench_contended_locks() {
|
||||
let manager = Arc::new(FastObjectLockManager::new());
|
||||
let concurrent_tasks = 50;
|
||||
let shared_objects = 10; // High contention on few objects
|
||||
let iterations_per_task = 50;
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let mut handles = Vec::new();
|
||||
for task_id in 0..concurrent_tasks {
|
||||
let manager_clone = manager.clone();
|
||||
let handle = task::spawn(async move {
|
||||
for i in 0..iterations_per_task {
|
||||
let object_name = format!("shared_{}", i % shared_objects);
|
||||
|
||||
// Mix of read and write operations
|
||||
if i % 3 == 0 {
|
||||
// Write operation
|
||||
if let Ok(_guard) = manager_clone
|
||||
.acquire_write_lock("bucket", &object_name, &format!("owner_{}", task_id))
|
||||
.await
|
||||
{
|
||||
tokio::task::yield_now().await;
|
||||
}
|
||||
} else {
|
||||
// Read operation
|
||||
if let Ok(_guard) = manager_clone
|
||||
.acquire_read_lock("bucket", &object_name, &format!("owner_{}", task_id))
|
||||
.await
|
||||
{
|
||||
tokio::task::yield_now().await;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
handles.push(handle);
|
||||
}
|
||||
|
||||
// Wait for all tasks
|
||||
for handle in handles {
|
||||
handle.await.unwrap();
|
||||
}
|
||||
|
||||
let duration = start.elapsed();
|
||||
|
||||
println!("Contended locks: {} tasks on {} objects in {:?}",
|
||||
concurrent_tasks, shared_objects, duration);
|
||||
|
||||
let metrics = manager.get_metrics();
|
||||
println!("Total acquisitions: {}", metrics.shard_metrics.total_acquisitions());
|
||||
println!("Fast path rate: {:.2}%", metrics.shard_metrics.fast_path_rate() * 100.0);
|
||||
println!("Average wait time: {:?}", metrics.shard_metrics.avg_wait_time());
|
||||
println!("Timeout rate: {:.2}%", metrics.shard_metrics.timeout_rate() * 100.0);
|
||||
|
||||
// Even with contention, should maintain reasonable performance
|
||||
assert!(metrics.shard_metrics.timeout_rate() < 0.1, "Should have <10% timeout rate");
|
||||
assert!(metrics.shard_metrics.avg_wait_time() < Duration::from_millis(100), "Avg wait should be <100ms");
|
||||
}
|
||||
|
||||
/// Benchmark batch operations
|
||||
#[tokio::test]
|
||||
async fn bench_batch_operations() {
|
||||
let manager = FastObjectLockManager::new();
|
||||
let batch_sizes = vec![10, 50, 100, 500];
|
||||
|
||||
for batch_size in batch_sizes {
|
||||
// Create batch request
|
||||
let mut batch = BatchLockRequest::new("batch_owner");
|
||||
for i in 0..batch_size {
|
||||
batch = batch.add_write_lock("bucket", &format!("batch_obj_{}", i));
|
||||
}
|
||||
|
||||
let start = Instant::now();
|
||||
let result = manager.acquire_locks_batch(batch).await;
|
||||
let duration = start.elapsed();
|
||||
|
||||
assert!(result.all_acquired, "Batch should succeed");
|
||||
println!("Batch size {}: {:?} ({:.2} μs per lock)",
|
||||
batch_size,
|
||||
duration,
|
||||
duration.as_micros() as f64 / batch_size as f64);
|
||||
|
||||
// Batch should be much faster than individual acquisitions
|
||||
assert!(duration.as_millis() < batch_size as u128 / 10,
|
||||
"Batch should be 10x+ faster than individual locks");
|
||||
}
|
||||
}
|
||||
|
||||
/// Benchmark version-specific locks
|
||||
#[tokio::test]
|
||||
async fn bench_versioned_locks() {
|
||||
let manager = Arc::new(FastObjectLockManager::new());
|
||||
let objects = 100;
|
||||
let versions_per_object = 10;
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let mut handles = Vec::new();
|
||||
for obj_id in 0..objects {
|
||||
let manager_clone = manager.clone();
|
||||
let handle = task::spawn(async move {
|
||||
for version in 0..versions_per_object {
|
||||
let _guard = manager_clone
|
||||
.acquire_write_lock_versioned(
|
||||
"bucket",
|
||||
&format!("obj_{}", obj_id),
|
||||
&format!("v{}", version),
|
||||
"version_owner"
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
});
|
||||
handles.push(handle);
|
||||
}
|
||||
|
||||
for handle in handles {
|
||||
handle.await.unwrap();
|
||||
}
|
||||
|
||||
let duration = start.elapsed();
|
||||
let total_ops = objects * versions_per_object;
|
||||
|
||||
println!("Versioned locks: {} version locks in {:?}", total_ops, duration);
|
||||
println!("Throughput: {:.2} locks/sec", total_ops as f64 / duration.as_secs_f64());
|
||||
|
||||
let metrics = manager.get_metrics();
|
||||
println!("Fast path rate: {:.2}%", metrics.shard_metrics.fast_path_rate() * 100.0);
|
||||
|
||||
// Versioned locks should not interfere with each other
|
||||
assert!(metrics.shard_metrics.fast_path_rate() > 0.9, "Should maintain high fast path rate");
|
||||
}
|
||||
|
||||
/// Compare with theoretical maximum performance
|
||||
#[tokio::test]
|
||||
async fn bench_theoretical_maximum() {
|
||||
let manager = Arc::new(FastObjectLockManager::new());
|
||||
let iterations = 100000;
|
||||
|
||||
// Measure pure fast path performance (no contention)
|
||||
let start = Instant::now();
|
||||
for i in 0..iterations {
|
||||
let _guard = manager
|
||||
.acquire_write_lock("bucket", &format!("unique_{}", i), "owner")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
let duration = start.elapsed();
|
||||
|
||||
println!("Theoretical maximum: {} unique locks in {:?}", iterations, duration);
|
||||
println!("Rate: {:.2} locks/sec", iterations as f64 / duration.as_secs_f64());
|
||||
println!("Latency: {:?} per lock", duration / iterations);
|
||||
|
||||
let metrics = manager.get_metrics();
|
||||
println!("Fast path rate: {:.2}%", metrics.shard_metrics.fast_path_rate() * 100.0);
|
||||
|
||||
// Should achieve very high performance with no contention
|
||||
assert!(metrics.shard_metrics.fast_path_rate() > 0.99, "Should be nearly 100% fast path");
|
||||
assert!(duration.as_secs_f64() / (iterations as f64) < 0.0001, "Should be <100μs per lock");
|
||||
}
|
||||
|
||||
/// Performance regression test
|
||||
#[tokio::test]
|
||||
async fn performance_regression_test() {
|
||||
let manager = Arc::new(FastObjectLockManager::new());
|
||||
|
||||
// This test ensures we maintain performance targets
|
||||
let test_cases = vec![
|
||||
("single_thread", 1, 10000),
|
||||
("low_contention", 10, 1000),
|
||||
("high_contention", 100, 100),
|
||||
];
|
||||
|
||||
for (test_name, threads, ops_per_thread) in test_cases {
|
||||
let start = Instant::now();
|
||||
|
||||
let mut handles = Vec::new();
|
||||
for thread_id in 0..threads {
|
||||
let manager_clone = manager.clone();
|
||||
let handle = task::spawn(async move {
|
||||
for op_id in 0..ops_per_thread {
|
||||
let object = if threads == 1 {
|
||||
format!("obj_{}_{}", thread_id, op_id)
|
||||
} else {
|
||||
format!("obj_{}", op_id % 100) // Create contention
|
||||
};
|
||||
|
||||
let owner = format!("owner_{}", thread_id);
|
||||
let _guard = manager_clone
|
||||
.acquire_write_lock("bucket", object, owner)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
});
|
||||
handles.push(handle);
|
||||
}
|
||||
|
||||
for handle in handles {
|
||||
handle.await.unwrap();
|
||||
}
|
||||
|
||||
let duration = start.elapsed();
|
||||
let total_ops = threads * ops_per_thread;
|
||||
let ops_per_sec = total_ops as f64 / duration.as_secs_f64();
|
||||
|
||||
println!("{}: {:.2} ops/sec", test_name, ops_per_sec);
|
||||
|
||||
// Performance targets (adjust based on requirements)
|
||||
match test_name {
|
||||
"single_thread" => assert!(ops_per_sec > 50000.0, "Single thread should exceed 50k ops/sec"),
|
||||
"low_contention" => assert!(ops_per_sec > 20000.0, "Low contention should exceed 20k ops/sec"),
|
||||
"high_contention" => assert!(ops_per_sec > 5000.0, "High contention should exceed 5k ops/sec"),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,9 +37,6 @@ pub mod shard;
|
||||
pub mod state;
|
||||
pub mod types;
|
||||
|
||||
// #[cfg(test)]
|
||||
// pub mod benchmarks; // Temporarily disabled due to compilation issues
|
||||
|
||||
// Re-export main types
|
||||
pub use disabled_manager::DisabledLockManager;
|
||||
pub use guard::FastLockGuard;
|
||||
|
||||
Reference in New Issue
Block a user