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)
This commit is contained in:
242
filetree-hybrid/src/copy_test.rs
Normal file
242
filetree-hybrid/src/copy_test.rs
Normal file
@@ -0,0 +1,242 @@
|
||||
use anyhow::Result;
|
||||
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!("=== Multi-File Copy Performance Test ===\n");
|
||||
|
||||
println!("Configuration:");
|
||||
println!(" Test files: 10,000");
|
||||
println!(" File size: 1KB each (total ~10MB)");
|
||||
println!(" Test 1: Traditional std::fs::copy");
|
||||
println!(" Test 2: Hybrid Architecture + Cache Warmup");
|
||||
println!(" Test 3: Comparison Analysis");
|
||||
|
||||
println!("\n=== Phase 1: Prepare Test Environment ===");
|
||||
|
||||
let test_dir = "/tmp/copy_test_source";
|
||||
let target_traditional = "/tmp/copy_test_traditional";
|
||||
let target_hybrid = "/tmp/copy_test_hybrid";
|
||||
|
||||
println!("\nStep 1: Create test files...");
|
||||
create_test_files(test_dir, 10000)?;
|
||||
|
||||
let test_files = collect_test_files(test_dir)?;
|
||||
println!(" ✓ Created {} test files", test_files.len());
|
||||
|
||||
println!("\n=== Phase 2: Traditional Copy Test ===");
|
||||
|
||||
fs::create_dir_all(target_traditional)?;
|
||||
let traditional_result = test_traditional_copy(&test_files, target_traditional)?;
|
||||
traditional_result.print_summary("Traditional std::fs::copy");
|
||||
|
||||
println!("\n=== Phase 3: Hybrid Copy Test (with Prepare) ===");
|
||||
|
||||
println!("\nStep 2: Initialize Hybrid Router...");
|
||||
use filetree_hybrid::HybridRouter;
|
||||
let router = HybridRouter::init_user_db("copy_test")?;
|
||||
|
||||
println!("\nStep 3: Prepare - Cache Warmup...");
|
||||
let warmup_start = Instant::now();
|
||||
|
||||
for (idx, file_path) in test_files.iter().enumerate().take(1000) {
|
||||
let file_name = file_path.file_name().unwrap().to_str().unwrap();
|
||||
let node = filetree_hybrid::HybridRouter::new_folder(file_name, None);
|
||||
router.insert_node(&node)?;
|
||||
|
||||
if idx % 100 == 0 {
|
||||
println!(" Warmup progress: {}/1000 files", idx);
|
||||
}
|
||||
}
|
||||
|
||||
let warmup_time = warmup_start.elapsed();
|
||||
println!(" ✓ Cache warmed up: {:?}", warmup_time);
|
||||
|
||||
println!("\nStep 4: Hybrid Copy (with cache lookup)...");
|
||||
fs::create_dir_all(target_hybrid)?;
|
||||
|
||||
let hybrid_start = Instant::now();
|
||||
let mut copied_files = 0;
|
||||
let mut total_bytes = 0;
|
||||
|
||||
for (idx, src_file) in test_files.iter().enumerate() {
|
||||
let file_name = src_file.file_name().unwrap().to_str().unwrap();
|
||||
|
||||
if let Some(_cache) = router.get_node(&file_name.replace(".", ""))? {
|
||||
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;
|
||||
} else {
|
||||
let target_file = Path::new(target_hybrid).join(file_name);
|
||||
fs::copy(src_file, &target_file)?;
|
||||
copied_files += 1;
|
||||
total_bytes += src_file.metadata()?.len();
|
||||
}
|
||||
|
||||
if idx % 1000 == 0 {
|
||||
println!(" Copy progress: {}/10000 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 Copy (with Prepare)");
|
||||
|
||||
println!("\n=== Phase 4: Performance Comparison ===");
|
||||
|
||||
println!("\nComparison Table:");
|
||||
println!("┌─────────────────────────────────────────┐");
|
||||
println!("│ Metric │ Traditional │ Hybrid │");
|
||||
println!("├─────────────────────────────────────────┤");
|
||||
println!(
|
||||
"│ Copy time │ {:?} │ {:?} │",
|
||||
traditional_result.copy_time, hybrid_result.copy_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!(
|
||||
"│ Speedup │ 1.00x │ {:.2}x │",
|
||||
traditional_result.copy_time.as_nanos() as f64 / hybrid_result.copy_time.as_nanos() as f64
|
||||
);
|
||||
println!("└─────────────────────────────────────────┘");
|
||||
|
||||
let speedup =
|
||||
traditional_result.copy_time.as_nanos() as f64 / hybrid_result.copy_time.as_nanos() as f64;
|
||||
|
||||
if speedup > 1.5 {
|
||||
println!("\n✅ SIGNIFICANT IMPROVEMENT: {:.2}x faster!", speedup);
|
||||
println!(" Hybrid architecture significantly improves multi-file copy performance.");
|
||||
} else if speedup > 1.1 {
|
||||
println!("\n✅ MODERATE IMPROVEMENT: {:.2}x faster", speedup);
|
||||
println!(" Hybrid architecture provides moderate improvement.");
|
||||
} else {
|
||||
println!("\n⚠️ NO SIGNIFICANT IMPROVEMENT: {:.2}x", speedup);
|
||||
println!(" Consider further optimizations:");
|
||||
println!(" - Larger cache warmup (more files)");
|
||||
println!(" - Batch copy operations");
|
||||
println!(" - Parallel copy threads");
|
||||
}
|
||||
|
||||
println!("\n=== Phase 5: Cleanup ===");
|
||||
|
||||
fs::remove_dir_all(test_dir)?;
|
||||
fs::remove_dir_all(target_traditional)?;
|
||||
fs::remove_dir_all(target_hybrid)?;
|
||||
|
||||
let db_path = filetree_hybrid::HybridRouter::user_db_path("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✅ Multi-File Copy Test completed successfully!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_test_files(dir: &str, count: usize) -> Result<()> {
|
||||
fs::create_dir_all(dir)?;
|
||||
|
||||
for i in 0..count {
|
||||
let file_path = Path::new(dir).join(format!("test_file_{:05}.txt", i));
|
||||
let mut file = fs::File::create(&file_path)?;
|
||||
|
||||
let content = format!("Test file {} content\n", i);
|
||||
file.write_all(content.as_bytes())?;
|
||||
|
||||
if i % 1000 == 0 {
|
||||
println!(" Creating progress: {}/{} files", 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 % 1000 == 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,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user