Files
markbase/filetree-hybrid/src/large_file_copy_test.rs
Warren 1300a4e223
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
MarkBase架构升级:Multi-Volume Virtual Tree + Dual-View Management + Git Remote修正
核心功能:
-  Categories/Series双视图管理(category_view.rs + import_markdown.rs)
-  FUSE Multi-Volume支持(tree_type参数)
-  SSH/SFTP/SCP/rsync协议完整实现(4042行)
-  NFS/SMB Module Phase 1-3完成
-  Archive Module Phase 1-4完成(2916行)
-  Download Center API完整实现
-  S3兼容API实现(560行)

Git配置修正:
-  删除错误origin(gitea.momentry.ddns.net)
-  删除m5max128(指向机器名)
-  设置origin = m5max128gitea.momentry.ddns.net/admin/markbase
-  设置m4minigitea = m4minigitea.momentry.ddns.net/warren/markbase

数据清理:
-  删除38个临时SQLite(保留accusys.sqlite、demo.sqlite)
-  删除.bak、test_*.bin、调试脚本等临时文件
-  删除临时目录(build/、download files/、raid_test/等)
-  更新.gitignore排除临时文件

架构优化:
- 52个文件修改,2434行新增,4739行删除
- Workspace成员整合(16个crate)
- 数据库状态:accusys.sqlite保留(主demo测试)

远程同步:
-  准备推送到m5max128gitea(远程Gitea)
-  准备推送到m4minigitea(本地Gitea)
2026-06-12 12:59:54 +08:00

311 lines
10 KiB
Rust

use anyhow::Result;
use filetree_hybrid::HybridRouter;
use std::fs;
use std::io::Write;
use std::path::Path;
use std::time::{Duration, Instant};
struct CopyTestResult {
total_files: usize,
total_size: u64,
copy_time: Duration,
throughput: f64,
avg_latency: Duration,
}
impl CopyTestResult {
fn print_summary(&self, label: &str) {
println!("\n{} Results:", label);
println!(" Files copied: {}", self.total_files);
println!(
" Total size: {:.2} MB",
self.total_size as f64 / 1024.0 / 1024.0
);
println!(" Copy time: {:?}", self.copy_time);
println!(" Throughput: {:.2} MB/sec", self.throughput);
println!(" Avg latency: {:?}", self.avg_latency);
}
}
fn main() -> Result<()> {
println!("=== Large File Copy Performance Test ===\n");
println!("Configuration:");
println!(" Test files: 100");
println!(" File size: 10MB each (total ~1GB)");
println!(" Test 1: Traditional std::fs::copy");
println!(" Test 2: Hybrid Architecture (Smart Warmup)");
println!(" Test 3: Repeated Copy (Cache Hit Benefit)");
println!("\n=== Phase 1: Prepare Large Files ===");
let test_dir = "/tmp/large_copy_test_source";
let target_traditional = "/tmp/large_copy_test_traditional";
let target_hybrid = "/tmp/large_copy_test_hybrid";
println!("\nStep 1: Create large test files (10MB each)...");
create_large_test_files(test_dir, 100, 10)?;
let test_files = collect_test_files(test_dir)?;
println!(" ✓ Created {} large files", test_files.len());
println!("\n=== Phase 2: Traditional Large File Copy ===");
fs::create_dir_all(target_traditional)?;
let traditional_result = test_traditional_copy(&test_files, target_traditional)?;
traditional_result.print_summary("Traditional Large File Copy");
println!("\n=== Phase 3: Hybrid Large File Copy (Smart Warmup) ===");
println!("\nStep 2: Initialize Hybrid Router...");
let router = HybridRouter::init_user_db("large_copy_test")?;
println!("\nStep 3: Smart Warmup (only top 10 hot files)...");
let warmup_start = Instant::now();
// Smart warmup: only warmup top 10 files (not all 100)
for (idx, file_path) in test_files.iter().enumerate().take(10) {
let file_name = file_path.file_name().unwrap().to_str().unwrap();
let node = HybridRouter::new_folder(file_name, None);
router.insert_node(&node)?;
if idx % 10 == 0 {
println!(" Warmup progress: {}/10 hot files", idx);
}
}
let warmup_time = warmup_start.elapsed();
println!(" ✓ Smart warmup time: {:?}", warmup_time);
println!(" (vs previous 346ms for 1000 files)");
println!(
" Reduction: {:.1}x faster warmup",
346.0 / warmup_time.as_millis() as f64
);
println!("\nStep 4: Hybrid Large File Copy...");
fs::create_dir_all(target_hybrid)?;
let hybrid_start = Instant::now();
let mut copied_files = 0;
let mut total_bytes = 0;
let mut cache_hits = 0;
for (idx, src_file) in test_files.iter().enumerate() {
let file_name = src_file.file_name().unwrap().to_str().unwrap();
// Hybrid copy with cache lookup
if router.get_node(&file_name.replace(".", ""))?.is_some() {
cache_hits += 1;
}
let target_file = Path::new(target_hybrid).join(file_name);
let file_size = src_file.metadata()?.len();
fs::copy(src_file, &target_file)?;
copied_files += 1;
total_bytes += file_size;
if idx % 20 == 0 {
println!(" Copy progress: {}/100 files", idx);
}
}
let hybrid_time = hybrid_start.elapsed();
let hybrid_result = CopyTestResult {
total_files: copied_files,
total_size: total_bytes,
copy_time: hybrid_time,
throughput: total_bytes as f64 / hybrid_time.as_secs_f64(),
avg_latency: hybrid_time / copied_files as u32,
};
hybrid_result.print_summary("Hybrid Large File Copy (Smart Warmup)");
println!("\n Cache statistics:");
println!(" Cache hits: {}", cache_hits);
println!(
" Cache hit rate: {:.1}%",
cache_hits as f64 / copied_files as f64 * 100.0
);
println!("\n=== Phase 4: Repeated Copy Test (Cache Benefit) ===");
println!("\nTest repeated copy of same file (10 times):");
let test_file = &test_files[0];
let file_name = test_file.file_name().unwrap().to_str().unwrap();
// First, add to cache
let node = HybridRouter::new_folder(file_name, None);
router.insert_node(&node)?;
let mut copy_times = Vec::new();
for i in 0..10 {
let target_file = Path::new(target_hybrid).join(format!("repeat_{}.dat", i));
let start = Instant::now();
fs::copy(test_file, &target_file)?;
let elapsed = start.elapsed();
copy_times.push(elapsed);
if i < 5 || i == 9 {
println!(" Copy {}: {:?}", i, elapsed);
}
}
println!("\nRepeated copy analysis:");
println!(" First copy: {:?}", copy_times[0]);
println!(" Avg subsequent copies: {:?}", {
let sum: Duration = copy_times[1..].iter().sum();
sum / (copy_times.len() - 1) as u32
});
let first_copy_ns = copy_times[0].as_nanos();
let avg_subsequent_ns =
copy_times[1..].iter().map(|d| d.as_nanos()).sum::<u128>() / (copy_times.len() - 1) as u128;
if first_copy_ns > avg_subsequent_ns {
let speedup = first_copy_ns as f64 / avg_subsequent_ns as f64;
println!(" Speedup: {:.2}x faster after first copy", speedup);
}
println!("\n=== Phase 5: Performance Comparison ===");
println!("\nComparison Table:");
println!("┌─────────────────────────────────────────┐");
println!("│ Metric │ Traditional │ Hybrid │");
println!("├─────────────────────────────────────────┤");
println!(
"│ Copy time │ {:?}{:?}",
traditional_result.copy_time, hybrid_result.copy_time
);
println!("│ Warmup overhead │ 0ms │ {:?}", warmup_time);
println!(
"│ Total time │ {:?}{:?}",
traditional_result.copy_time,
hybrid_time + warmup_time
);
println!(
"│ Throughput │ {:.2} MB/s │ {:.2} MB/s │",
traditional_result.throughput / 1024.0 / 1024.0,
hybrid_result.throughput / 1024.0 / 1024.0
);
println!(
"│ Avg latency │ {:?}{:?}",
traditional_result.avg_latency, hybrid_result.avg_latency
);
println!("└─────────────────────────────────────────┘");
let total_traditional = traditional_result.copy_time;
let total_hybrid = hybrid_time + warmup_time;
let speedup = total_traditional.as_nanos() as f64 / total_hybrid.as_nanos() as f64;
println!("\nOverall Speedup: {:.2}x", speedup);
if speedup > 1.5 {
println!("\n✅ SIGNIFICANT IMPROVEMENT!");
println!(
" Hybrid architecture with smart warmup significantly improves large file copy."
);
} else if speedup > 1.1 {
println!("\n✅ MODERATE IMPROVEMENT!");
println!(" Hybrid architecture provides moderate improvement for large files.");
} else {
println!("\n⚠️ NO IMPROVEMENT");
println!(" Further optimizations needed:");
println!(" - Batch copy operations");
println!(" - Parallel copy threads");
println!(" - Cache hit optimization");
}
println!("\n=== Phase 6: Cleanup ===");
fs::remove_dir_all(test_dir)?;
fs::remove_dir_all(target_traditional)?;
fs::remove_dir_all(target_hybrid)?;
let db_path = HybridRouter::user_db_path("large_copy_test");
let sqlite_path = format!("{}.sqlite", db_path);
let sled_path = format!("{}.sled", db_path);
fs::remove_file(&sqlite_path)?;
fs::remove_dir_all(&sled_path)?;
println!(" ✓ Test environment cleaned up");
println!("\n✅ Large File Copy Test completed successfully!");
Ok(())
}
fn create_large_test_files(dir: &str, count: usize, size_mb: usize) -> Result<()> {
fs::create_dir_all(dir)?;
println!(" Creating {} large files ({}MB each)...", count, size_mb);
for i in 0..count {
let file_path = Path::new(dir).join(format!("large_file_{:05}.dat", i));
let mut file = fs::File::create(&file_path)?;
// Write specified size of data
let size_bytes = size_mb * 1024 * 1024;
let chunk_size = 1024 * 1024; // 1MB chunks
let data = vec![0u8; chunk_size];
for _ in 0..(size_bytes / chunk_size) {
file.write_all(&data)?;
}
if i % 20 == 0 {
println!(" Progress: {}/{} files created", i, count);
}
}
Ok(())
}
fn collect_test_files(dir: &str) -> Result<Vec<std::path::PathBuf>> {
let mut files = Vec::new();
for entry in fs::read_dir(dir)? {
let entry = entry?;
if entry.file_type()?.is_file() {
files.push(entry.path());
}
}
Ok(files)
}
fn test_traditional_copy(files: &[std::path::PathBuf], target: &str) -> Result<CopyTestResult> {
let start = Instant::now();
let mut copied_files = 0;
let mut total_bytes = 0;
for (idx, src_file) in files.iter().enumerate() {
let file_name = src_file.file_name().unwrap().to_str().unwrap();
let target_file = Path::new(target).join(file_name);
let file_size = src_file.metadata()?.len();
fs::copy(src_file, &target_file)?;
copied_files += 1;
total_bytes += file_size;
if idx % 20 == 0 {
println!(" Copy progress: {}/{} files", idx, files.len());
}
}
let elapsed = start.elapsed();
Ok(CopyTestResult {
total_files: copied_files,
total_size: total_bytes,
copy_time: elapsed,
throughput: total_bytes as f64 / elapsed.as_secs_f64(),
avg_latency: elapsed / copied_files as u32,
})
}