核心功能: - ✅ 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)
144 lines
5.1 KiB
Rust
144 lines
5.1 KiB
Rust
use anyhow::Result;
|
|
use filetree_hybrid::HybridRouter;
|
|
use std::time::Instant;
|
|
|
|
fn main() -> Result<()> {
|
|
println!("=== Hybrid Architecture POC Test ===\n");
|
|
|
|
let user_id = "test_hybrid";
|
|
|
|
println!("Step 1: Initialize Hybrid database...");
|
|
let start = Instant::now();
|
|
let router = HybridRouter::init_user_db(user_id)?;
|
|
let init_time = start.elapsed();
|
|
println!(" ✓ Init time: {:?}", init_time);
|
|
|
|
println!("\nStep 2: Insert 1,000 nodes (dual-write)...");
|
|
let nodes: Vec<filetree_hybrid::FileNode> = (0..1000)
|
|
.map(|i| HybridRouter::new_folder(&format!("folder_{}", i), None))
|
|
.collect();
|
|
|
|
let start = Instant::now();
|
|
for node in &nodes {
|
|
router.insert_node(node)?;
|
|
}
|
|
let single_insert_time = start.elapsed();
|
|
let single_throughput = nodes.len() as f64 / single_insert_time.as_secs_f64();
|
|
println!(" ✓ Single insert: {:?}", single_insert_time);
|
|
println!(" ✓ Throughput: {:.2} nodes/sec", single_throughput);
|
|
|
|
println!("\nStep 3: Insert 10,000 nodes (batch dual-write)...");
|
|
let nodes_batch: Vec<filetree_hybrid::FileNode> = (0..10000)
|
|
.map(|i| HybridRouter::new_folder(&format!("batch_folder_{}", i), None))
|
|
.collect();
|
|
|
|
let start = Instant::now();
|
|
router.insert_node_batch(&nodes_batch)?;
|
|
let batch_insert_time = start.elapsed();
|
|
let batch_throughput = nodes_batch.len() as f64 / batch_insert_time.as_secs_f64();
|
|
println!(" ✓ Batch insert: {:?}", batch_insert_time);
|
|
println!(" ✓ Throughput: {:.2} nodes/sec", batch_throughput);
|
|
|
|
println!("\nStep 4: Query node (cache hit test)...");
|
|
let test_node_id = &nodes_batch[5000].node_id;
|
|
|
|
println!(" First query (cache miss, SQLite query):");
|
|
let start = Instant::now();
|
|
let node1 = router.get_node(test_node_id)?;
|
|
let query1_time = start.elapsed();
|
|
println!(" ✓ Query time: {:?}", query1_time);
|
|
println!(" ✓ Found: {}", node1.is_some());
|
|
|
|
println!(" Second query (cache hit, Sled cache):");
|
|
let start = Instant::now();
|
|
let node2 = router.get_node(test_node_id)?;
|
|
let query2_time = start.elapsed();
|
|
println!(" ✓ Query time: {:?}", query2_time);
|
|
println!(" ✓ Found: {}", node2.is_some());
|
|
println!(
|
|
" ✓ Speedup: {:.2}x",
|
|
query1_time.as_nanos() as f64 / query2_time.as_nanos() as f64
|
|
);
|
|
|
|
println!("\nStep 5: Get children (SQLite query)...");
|
|
let parent_id = &nodes[0].node_id;
|
|
let start = Instant::now();
|
|
let children = router.get_children(parent_id)?;
|
|
let children_time = start.elapsed();
|
|
println!(" ✓ Query time: {:?}", children_time);
|
|
println!(" ✓ Children count: {}", children.len());
|
|
|
|
println!("\nStep 6: Cache metrics...");
|
|
let metrics = router.get_metrics();
|
|
println!(" ✓ Cache hits: {}", metrics.cache_hits);
|
|
println!(" ✓ Cache misses: {}", metrics.cache_misses);
|
|
println!(" ✓ Hit rate: {:.2}%", metrics.hit_rate() * 100.0);
|
|
println!(" ✓ Avg cache latency: {:?}", metrics.avg_cache_latency);
|
|
println!(" ✓ Avg SQLite latency: {:?}", metrics.avg_sqlite_latency);
|
|
|
|
println!("\nStep 7: Database sizes...");
|
|
let sqlite_count = router.count_nodes()?;
|
|
let sled_count = router.cache_size()?;
|
|
println!(" ✓ SQLite nodes: {}", sqlite_count);
|
|
println!(" ✓ Sled cache entries: {}", sled_count);
|
|
|
|
let db_path = HybridRouter::user_db_path(user_id);
|
|
let sqlite_path = format!("{}.sqlite", db_path);
|
|
let sled_path = format!("{}.sled", db_path);
|
|
|
|
let sqlite_size = std::fs::metadata(&sqlite_path)?.len();
|
|
let sled_size = get_directory_size(&sled_path)?;
|
|
println!(
|
|
" ✓ SQLite size: {:.2} MB",
|
|
sqlite_size as f64 / 1024.0 / 1024.0
|
|
);
|
|
println!(
|
|
" ✓ Sled size: {:.2} MB",
|
|
sled_size as f64 / 1024.0 / 1024.0
|
|
);
|
|
println!(
|
|
" ✓ Total size: {:.2} MB",
|
|
(sqlite_size + sled_size) as f64 / 1024.0 / 1024.0
|
|
);
|
|
|
|
println!("\n=== Performance Summary ===");
|
|
println!(
|
|
"Single insert: {:?} ({:.2} nodes/sec)",
|
|
single_insert_time, single_throughput
|
|
);
|
|
println!(
|
|
"Batch insert: {:?} ({:.2} nodes/sec)",
|
|
batch_insert_time, batch_throughput
|
|
);
|
|
println!("Query cache miss: {:?}", query1_time);
|
|
println!("Query cache hit: {:?}", query2_time);
|
|
println!(
|
|
"Cache speedup: {:.2}x",
|
|
query1_time.as_nanos() as f64 / query2_time.as_nanos() as f64
|
|
);
|
|
println!("Cache hit rate: {:.2}%", metrics.hit_rate() * 100.0);
|
|
|
|
println!("\nStep 8: Cleanup...");
|
|
std::fs::remove_file(&sqlite_path)?;
|
|
std::fs::remove_dir_all(&sled_path)?;
|
|
println!(" ✓ Test database removed");
|
|
|
|
println!("\n✅ Hybrid POC Test completed successfully!");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn get_directory_size(path: &str) -> Result<u64> {
|
|
let mut total_size = 0;
|
|
for entry in std::fs::read_dir(path)? {
|
|
let entry = entry?;
|
|
let metadata = entry.metadata()?;
|
|
if metadata.is_file() {
|
|
total_size += metadata.len();
|
|
} else if metadata.is_dir() {
|
|
total_size += get_directory_size(entry.path().to_str().unwrap())?;
|
|
}
|
|
}
|
|
Ok(total_size)
|
|
}
|