Skip to main content

download_compare/
download_compare.rs

1use baidu_netdisk_sdk::BaiduNetDiskClient;
2use log::info;
3use std::path::Path;
4
5const CHUNK_SIZE: u64 = 4 * 1024 * 1024;
6
7#[tokio::main]
8async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
9    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
10
11    let client = BaiduNetDiskClient::builder().build()?;
12    info!("Client created successfully");
13
14    client.load_token_from_env()?;
15    info!("Token loaded successfully");
16
17    println!("=== Baidu NetDisk Download Comparison Test ===");
18    println!();
19    println!(
20        "Enter the number of threads/concurrency to use (recommended: match your CPU core count)"
21    );
22    println!("Example: 4 for 4 cores, 8 for 8 cores, etc.");
23    let mut input = String::new();
24    std::io::stdin().read_line(&mut input)?;
25    let thread_num: usize = input.trim().parse().unwrap_or(4);
26    let concurrency = thread_num * 3;
27    println!();
28    println!("Thread count: {}", thread_num);
29    println!("Concurrency: {}", concurrency);
30    println!();
31
32    println!("=== Method 1: Streaming (Futures/Concurrency) ===");
33    println!("Enter the remote file path to download:");
34    let mut input = String::new();
35    std::io::stdin().read_line(&mut input)?;
36    let remote_path_streaming = input.trim();
37
38    if remote_path_streaming.is_empty() {
39        eprintln!("Error: File path cannot be empty");
40        return Ok(());
41    }
42
43    println!("\n--- Step 1: Get file info for Streaming ---");
44    let file_info_streaming = client.file().get_file_info(remote_path_streaming).await?;
45    let file_size_streaming = file_info_streaming.size.unwrap_or(0);
46    let fs_id_streaming = file_info_streaming.fs_id.ok_or("File has no fs_id")?;
47    let file_meta_streaming = client.file().get_file_meta(fs_id_streaming).await?;
48
49    println!("File: {}", file_info_streaming.name);
50    println!(
51        "Size: {} bytes ({:.2} MB)",
52        file_size_streaming,
53        file_size_streaming as f64 / (1024.0 * 1024.0)
54    );
55    let total_chunks_streaming = (file_size_streaming + CHUNK_SIZE - 1) / CHUNK_SIZE;
56    println!(
57        "Chunks: {} ({} bytes each)",
58        total_chunks_streaming, CHUNK_SIZE
59    );
60    println!();
61
62    println!("Press Enter to start Streaming download...");
63    std::io::stdin().read_line(&mut String::new())?;
64
65    let streaming_save_path = format!("./download_streaming_{}", file_info_streaming.name);
66    let start_streaming = std::time::Instant::now();
67
68    client
69        .download()
70        .download_streaming_with_meta(
71            &file_meta_streaming,
72            Path::new(&streaming_save_path),
73            concurrency,
74        )
75        .await?;
76
77    let duration_streaming = start_streaming.elapsed();
78    let streaming_mb = file_size_streaming as f64 / (1024.0 * 1024.0);
79    let streaming_sec = duration_streaming.as_secs_f64();
80    let streaming_speed = streaming_mb / streaming_sec;
81
82    println!();
83    println!("=== Method 2: Parallel (Multi-thread) ===");
84    println!("Enter the remote file path to download:");
85    let mut input = String::new();
86    std::io::stdin().read_line(&mut input)?;
87    let remote_path_parallel = input.trim();
88
89    if remote_path_parallel.is_empty() {
90        eprintln!("Error: File path cannot be empty");
91        return Ok(());
92    }
93
94    println!("\n--- Step 1: Get file info for Parallel ---");
95    let file_info_parallel = client.file().get_file_info(remote_path_parallel).await?;
96    let file_size_parallel = file_info_parallel.size.unwrap_or(0);
97    let fs_id_parallel = file_info_parallel.fs_id.ok_or("File has no fs_id")?;
98    let file_meta_parallel = client.file().get_file_meta(fs_id_parallel).await?;
99
100    println!("File: {}", file_info_parallel.name);
101    println!(
102        "Size: {} bytes ({:.2} MB)",
103        file_size_parallel,
104        file_size_parallel as f64 / (1024.0 * 1024.0)
105    );
106    let total_chunks_parallel = (file_size_parallel + CHUNK_SIZE - 1) / CHUNK_SIZE;
107    println!(
108        "Chunks: {} ({} bytes each)",
109        total_chunks_parallel, CHUNK_SIZE
110    );
111    println!();
112
113    println!("Press Enter to start Parallel download...");
114    std::io::stdin().read_line(&mut String::new())?;
115
116    let parallel_save_path = format!("./download_parallel_{}", file_info_parallel.name);
117    let start_parallel = std::time::Instant::now();
118
119    client
120        .download()
121        .download_parallel_multi_threaded(
122            &file_meta_parallel,
123            Path::new(&parallel_save_path),
124            Some(thread_num),
125        )
126        .await?;
127
128    let duration_parallel = start_parallel.elapsed();
129    let parallel_mb = file_size_parallel as f64 / (1024.0 * 1024.0);
130    let parallel_sec = duration_parallel.as_secs_f64();
131    let parallel_speed = parallel_mb / parallel_sec;
132
133    println!();
134    println!("╔══════════════════════════════════════════════════════════════════════════╗");
135    println!("║                        DOWNLOAD COMPARISON RESULTS                         ║");
136    println!("╠══════════════════════════════════════════════════════════════════════════╣");
137    println!(
138        "║  Threads: {}  │  Concurrency (Streaming): {}  │                  ║",
139        thread_num, concurrency
140    );
141    println!("╠══════════════════════════════════════════════════════════════════════════╣");
142    println!("║  Method                      │ Time       │ Speed       │ File           ║");
143    println!("╠══════════════════════════════════════════════════════════════════════════╣");
144    println!(
145        "║  Streaming (Futures)         │ {:>8.2}s  │ {:>8.2} MB/s │ {:.15} ║",
146        streaming_sec, streaming_speed, file_info_streaming.name
147    );
148    println!(
149        "║  Parallel (Multi-thread)     │ {:>8.2}s  │ {:>8.2} MB/s │ {:.15} ║",
150        parallel_sec, parallel_speed, file_info_parallel.name
151    );
152    println!("╠══════════════════════════════════════════════════════════════════════════╣");
153    let speedup = if streaming_sec < parallel_sec {
154        parallel_sec / streaming_sec
155    } else {
156        streaming_sec / parallel_sec
157    };
158    let faster = if streaming_sec < parallel_sec {
159        "Streaming"
160    } else {
161        "Parallel"
162    };
163    println!(
164        "║  Faster: {} ({:.2}x)                                              ║",
165        faster, speedup
166    );
167    println!("╠══════════════════════════════════════════════════════════════════════════╣");
168    println!("║  Note: Parallel mode works best with 6+ cores. On 4 cores, Streaming may  ║");
169    println!("║        be 2x faster. Test with your actual core count for best results!   ║");
170    println!("╚══════════════════════════════════════════════════════════════════════════╝");
171
172    println!();
173    println!("Output files:");
174    println!("  Parallel:   {}", parallel_save_path);
175    println!("  Streaming:  {}", streaming_save_path);
176
177    Ok(())
178}