iT邦幫忙

2025 iThome 鐵人賽

DAY 27
0
Rust

Rust 實戰專案集:30 個漸進式專案從工具到服務系列 第 27

系統效能基準測試 - CPU/磁碟/網路效能測試工具

  • 分享至 

  • xImage
  •  

前言

在這個專案中,我們建立一個全面的系統效能基準測試工具。
這個工具能夠測試 CPU、磁碟和網路的效能,
提供詳細的測試報告,幫助開發者和系統管理員了解系統的效能瓶頸。
目前鐵人賽已經接近尾聲,關於系統工具相關的學習和思考,
這已經是最後一篇,明天會考慮做整合相關的部分

今日學習目標

  • 實作 CPU 密集運算的基準測試
  • 測試磁碟的讀寫效能
  • 評估網路的延遲和吞吐量
  • 產生詳細的測試報告
  • 使用多執行緒進行並行測試

專案建置

cargo new system-benchmark
cd system-benchmark

依賴

cargo.toml

[package]
name = "system-benchmark"
version = "0.1.0"
edition = "2021"

[dependencies]
clap = { version = "4.5", features = ["derive"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1.40", features = ["full"] }
anyhow = "1.0"
chrono = "0.4"
num_cpus = "1.16"
rand = "0.8"
indicatif = "0.17"
colored = "2.1"

一樣,我們先把資料結構弄出來

src/models.rs

use serde::{Deserialize, Serialize};
use std::time::Duration;

#[derive(Debug, Serialize, Deserialize)]
pub struct BenchmarkResult {
    pub test_name: String,
    pub duration: Duration,
    pub timestamp: String,
    pub cpu_results: Option<CpuBenchmark>,
    pub disk_results: Option<DiskBenchmark>,
    pub network_results: Option<NetworkBenchmark>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CpuBenchmark {
    pub single_thread_score: f64,
    pub multi_thread_score: f64,
    pub cores_used: usize,
    pub operations_per_second: u64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct DiskBenchmark {
    pub sequential_read_mbps: f64,
    pub sequential_write_mbps: f64,
    pub random_read_iops: f64,
    pub random_write_iops: f64,
    pub test_file_size_mb: usize,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct NetworkBenchmark {
    pub latency_ms: f64,
    pub download_mbps: f64,
    pub upload_mbps: f64,
    pub packet_loss_percent: f64,
    pub test_host: String,
}

這裡我們針對 CPU 進行基準測試(benchmark)

src/cpu_bench.rs

use anyhow::Result;
use std::time::Instant;
use crate::models::CpuBenchmark;

pub struct CpuBenchmarker {
    cores: usize,
}

impl CpuBenchmarker {
    pub fn new() -> Self {
        Self {
            cores: num_cpus::get(),
        }
    }

    pub fn run_benchmark(&self, duration_secs: u64) -> Result<CpuBenchmark> {
        println!("🔧 執行 CPU 基準測試...");
        
        // 單執行緒測試
        let single_score = self.run_single_thread_test(duration_secs)?;
        
        // 多執行緒測試
        let multi_score = self.run_multi_thread_test(duration_secs)?;
        
        let ops_per_sec = (multi_score as u64) * 1_000_000;
        
        Ok(CpuBenchmark {
            single_thread_score: single_score,
            multi_thread_score: multi_score,
            cores_used: self.cores,
            operations_per_second: ops_per_sec,
        })
    }

    fn run_single_thread_test(&self, duration_secs: u64) -> Result<f64> {
        let start = Instant::now();
        let mut operations = 0u64;
        
        while start.elapsed().as_secs() < duration_secs {
            // 執行 CPU 密集運算:質數計算
            operations += self.calculate_primes(10000) as u64;
        }
        
        let elapsed = start.elapsed().as_secs_f64();
        Ok(operations as f64 / elapsed)
    }

    fn run_multi_thread_test(&self, duration_secs: u64) -> Result<f64> {
        use std::sync::{Arc, Mutex};
        use std::thread;
        
        let operations = Arc::new(Mutex::new(0u64));
        let mut handles = vec![];
        
        let start = Instant::now();
        
        for _ in 0..self.cores {
            let ops = Arc::clone(&operations);
            let duration = duration_secs;
            
            let handle = thread::spawn(move || {
                let thread_start = Instant::now();
                let mut local_ops = 0u64;
                
                while thread_start.elapsed().as_secs() < duration {
                    local_ops += Self::calculate_primes_static(10000) as u64;
                }
                
                let mut ops = ops.lock().unwrap();
                *ops += local_ops;
            });
            
            handles.push(handle);
        }
        
        for handle in handles {
            handle.join().unwrap();
        }
        
        let elapsed = start.elapsed().as_secs_f64();
        let total_ops = *operations.lock().unwrap();
        
        Ok(total_ops as f64 / elapsed)
    }

    fn calculate_primes(&self, limit: usize) -> usize {
        Self::calculate_primes_static(limit)
    }

    fn calculate_primes_static(limit: usize) -> usize {
        let mut primes = vec![true; limit];
        let mut count = 0;
        
        for i in 2..limit {
            if primes[i] {
                count += 1;
                let mut j = i * i;
                while j < limit {
                    primes[j] = false;
                    j += i;
                }
            }
        }
        
        count
    }
}

硬碟基準測試

src/disk_bench.rs

use anyhow::Result;
use rand::Rng;
use std::fs::{File, OpenOptions};
use std::io::{Read, Seek, SeekFrom, Write};
use std::time::Instant;
use crate::models::DiskBenchmark;

pub struct DiskBenchmarker {
    test_file_path: String,
    file_size_mb: usize,
}

impl DiskBenchmarker {
    pub fn new(test_file_path: String, file_size_mb: usize) -> Self {
        Self {
            test_file_path,
            file_size_mb,
        }
    }

    pub fn run_benchmark(&self) -> Result<DiskBenchmark> {
        println!("💾 執行磁碟基準測試...");
        
        // 順序寫入測試
        let seq_write = self.test_sequential_write()?;
        
        // 順序讀取測試
        let seq_read = self.test_sequential_read()?;
        
        // 隨機寫入測試
        let rand_write = self.test_random_write()?;
        
        // 隨機讀取測試
        let rand_read = self.test_random_read()?;
        
        // 清理測試檔案
        std::fs::remove_file(&self.test_file_path).ok();
        
        Ok(DiskBenchmark {
            sequential_read_mbps: seq_read,
            sequential_write_mbps: seq_write,
            random_read_iops: rand_read,
            random_write_iops: rand_write,
            test_file_size_mb: self.file_size_mb,
        })
    }

    fn test_sequential_write(&self) -> Result<f64> {
        let mut file = File::create(&self.test_file_path)?;
        let buffer = vec![0u8; 1024 * 1024]; // 1MB buffer
        
        let start = Instant::now();
        
        for _ in 0..self.file_size_mb {
            file.write_all(&buffer)?;
        }
        
        file.sync_all()?;
        let elapsed = start.elapsed().as_secs_f64();
        
        Ok(self.file_size_mb as f64 / elapsed)
    }

    fn test_sequential_read(&self) -> Result<f64> {
        let mut file = File::open(&self.test_file_path)?;
        let mut buffer = vec![0u8; 1024 * 1024];
        
        let start = Instant::now();
        
        loop {
            let bytes_read = file.read(&mut buffer)?;
            if bytes_read == 0 {
                break;
            }
        }
        
        let elapsed = start.elapsed().as_secs_f64();
        
        Ok(self.file_size_mb as f64 / elapsed)
    }

    fn test_random_write(&self) -> Result<f64> {
        let mut file = OpenOptions::new()
            .write(true)
            .open(&self.test_file_path)?;
        
        let buffer = vec![0u8; 4096]; // 4KB blocks
        let mut rng = rand::thread_rng();
        let max_offset = (self.file_size_mb * 1024 * 1024) - 4096;
        
        let operations = 1000;
        let start = Instant::now();
        
        for _ in 0..operations {
            let offset = rng.gen_range(0..max_offset) as u64;
            file.seek(SeekFrom::Start(offset))?;
            file.write_all(&buffer)?;
        }
        
        file.sync_all()?;
        let elapsed = start.elapsed().as_secs_f64();
        
        Ok(operations as f64 / elapsed)
    }

    fn test_random_read(&self) -> Result<f64> {
        let mut file = File::open(&self.test_file_path)?;
        let mut buffer = vec![0u8; 4096];
        let mut rng = rand::thread_rng();
        let max_offset = (self.file_size_mb * 1024 * 1024) - 4096;
        
        let operations = 1000;
        let start = Instant::now();
        
        for _ in 0..operations {
            let offset = rng.gen_range(0..max_offset) as u64;
            file.seek(SeekFrom::Start(offset))?;
            file.read_exact(&mut buffer)?;
        }
        
        let elapsed = start.elapsed().as_secs_f64();
        
        Ok(operations as f64 / elapsed)
    }
}

網路基準測試

src/network_bench.rs

use anyhow::Result;
use std::time::Instant;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;
use tokio::time::{sleep, Duration};
use crate::models::NetworkBenchmark;

pub struct NetworkBenchmarker {
    test_host: String,
}

impl NetworkBenchmarker {
    pub fn new(test_host: String) -> Self {
        Self { test_host }
    }

    pub async fn run_benchmark(&self) -> Result<NetworkBenchmark> {
        println!("🌐 執行網路基準測試...");
        
        // 延遲測試
        let latency = self.test_latency().await?;
        
        // 下載速度測試 (模擬)
        let download_speed = self.test_download_speed().await?;
        
        // 上傳速度測試 (模擬)
        let upload_speed = self.test_upload_speed().await?;
        
        // 封包遺失測試
        let packet_loss = self.test_packet_loss().await?;
        
        Ok(NetworkBenchmark {
            latency_ms: latency,
            download_mbps: download_speed,
            upload_mbps: upload_speed,
            packet_loss_percent: packet_loss,
            test_host: self.test_host.clone(),
        })
    }

    async fn test_latency(&self) -> Result<f64> {
        let mut total_latency = 0.0;
        let tests = 10;
        
        for _ in 0..tests {
            let start = Instant::now();
            
            // 嘗試連接到目標主機
            match TcpStream::connect(&self.test_host).await {
                Ok(_) => {
                    let latency = start.elapsed().as_secs_f64() * 1000.0;
                    total_latency += latency;
                }
                Err(_) => {
                    // 如果連接失敗,使用預設延遲
                    total_latency += 50.0;
                }
            }
            
            sleep(Duration::from_millis(100)).await;
        }
        
        Ok(total_latency / tests as f64)
    }

    async fn test_download_speed(&self) -> Result<f64> {
        // 這是一個簡化的模擬測試
        // 實際應用中應該連接到測速伺服器
        
        match TcpStream::connect(&self.test_host).await {
            Ok(mut stream) => {
                let mut buffer = vec![0u8; 8192];
                let mut total_bytes = 0;
                let start = Instant::now();
                let test_duration = Duration::from_secs(3);
                
                while start.elapsed() < test_duration {
                    match stream.read(&mut buffer).await {
                        Ok(n) if n > 0 => total_bytes += n,
                        _ => break,
                    }
                }
                
                let elapsed = start.elapsed().as_secs_f64();
                let mbps = (total_bytes as f64 * 8.0) / (elapsed * 1_000_000.0);
                
                Ok(mbps)
            }
            Err(_) => Ok(0.0),
        }
    }

    async fn test_upload_speed(&self) -> Result<f64> {
        match TcpStream::connect(&self.test_host).await {
            Ok(mut stream) => {
                let buffer = vec![0u8; 8192];
                let mut total_bytes = 0;
                let start = Instant::now();
                let test_duration = Duration::from_secs(3);
                
                while start.elapsed() < test_duration {
                    match stream.write(&buffer).await {
                        Ok(n) => total_bytes += n,
                        Err(_) => break,
                    }
                }
                
                let elapsed = start.elapsed().as_secs_f64();
                let mbps = (total_bytes as f64 * 8.0) / (elapsed * 1_000_000.0);
                
                Ok(mbps)
            }
            Err(_) => Ok(0.0),
        }
    }

    async fn test_packet_loss(&self) -> Result<f64> {
        let total_tests = 20;
        let mut failed = 0;
        
        for _ in 0..total_tests {
            if TcpStream::connect(&self.test_host).await.is_err() {
                failed += 1;
            }
            sleep(Duration::from_millis(50)).await;
        }
        
        Ok((failed as f64 / total_tests as f64) * 100.0)
    }
}

根據以上狀態產生報告 - 報告生成器

src/reporter.rs

use anyhow::Result;
use chrono::Local;
use colored::*;
use std::fs::File;
use std::io::Write;
use crate::models::BenchmarkResult;

pub struct Reporter;

impl Reporter {
    pub fn print_results(result: &BenchmarkResult) {
        println!("\n{}", "═══════════════════════════════════════".blue().bold());
        println!("{}", "      系統效能基準測試報告".blue().bold());
        println!("{}", "═══════════════════════════════════════".blue().bold());
        
        println!("\n📊 測試資訊:");
        println!("  測試名稱: {}", result.test_name);
        println!("  測試時間: {}", result.timestamp);
        println!("  總耗時: {:.2}秒", result.duration.as_secs_f64());
        
        if let Some(cpu) = &result.cpu_results {
            println!("\n🔧 CPU 測試結果:");
            println!("  單執行緒分數: {:.2}", cpu.single_thread_score);
            println!("  多執行緒分數: {:.2}", cpu.multi_thread_score);
            println!("  使用核心數: {}", cpu.cores_used);
            println!("  每秒運算次數: {}", cpu.operations_per_second);
            
            let speedup = cpu.multi_thread_score / cpu.single_thread_score;
            let efficiency = (speedup / cpu.cores_used as f64) * 100.0;
            println!("  多核加速比: {:.2}x", speedup);
            println!("  並行效率: {:.1}%", efficiency);
        }
        
        if let Some(disk) = &result.disk_results {
            println!("\n💾 磁碟測試結果:");
            println!("  順序讀取: {:.2} MB/s", disk.sequential_read_mbps);
            println!("  順序寫入: {:.2} MB/s", disk.sequential_write_mbps);
            println!("  隨機讀取: {:.2} IOPS", disk.random_read_iops);
            println!("  隨機寫入: {:.2} IOPS", disk.random_write_iops);
            println!("  測試檔案大小: {} MB", disk.test_file_size_mb);
        }
        
        if let Some(net) = &result.network_results {
            println!("\n🌐 網路測試結果:");
            println!("  測試主機: {}", net.test_host);
            println!("  延遲: {:.2} ms", net.latency_ms);
            println!("  下載速度: {:.2} Mbps", net.download_mbps);
            println!("  上傳速度: {:.2} Mbps", net.upload_mbps);
            println!("  封包遺失率: {:.2}%", net.packet_loss_percent);
        }
        
        println!("\n{}", "═══════════════════════════════════════".blue().bold());
    }

    pub fn save_to_file(result: &BenchmarkResult, filename: &str) -> Result<()> {
        let json = serde_json::to_string_pretty(result)?;
        let mut file = File::create(filename)?;
        file.write_all(json.as_bytes())?;
        
        println!("\n✅ 測試結果已儲存至: {}", filename.green());
        Ok(())
    }

    pub fn generate_markdown_report(result: &BenchmarkResult, filename: &str) -> Result<()> {
        let mut content = String::new();
        
        content.push_str(&format!("# 系統效能基準測試報告\n\n"));
        content.push_str(&format!("**測試時間:** {}\n\n", result.timestamp));
        content.push_str(&format!("**測試名稱:** {}\n\n", result.test_name));
        
        if let Some(cpu) = &result.cpu_results {
            content.push_str("## CPU 測試結果\n\n");
            content.push_str("| 項目 | 數值 |\n");
            content.push_str("|------|------|\n");
            content.push_str(&format!("| 單執行緒分數 | {:.2} |\n", cpu.single_thread_score));
            content.push_str(&format!("| 多執行緒分數 | {:.2} |\n", cpu.multi_thread_score));
            content.push_str(&format!("| 使用核心數 | {} |\n", cpu.cores_used));
            content.push_str(&format!("| 每秒運算次數 | {} |\n\n", cpu.operations_per_second));
        }
        
        if let Some(disk) = &result.disk_results {
            content.push_str("## 磁碟測試結果\n\n");
            content.push_str("| 項目 | 數值 |\n");
            content.push_str("|------|------|\n");
            content.push_str(&format!("| 順序讀取 | {:.2} MB/s |\n", disk.sequential_read_mbps));
            content.push_str(&format!("| 順序寫入 | {:.2} MB/s |\n", disk.sequential_write_mbps));
            content.push_str(&format!("| 隨機讀取 | {:.2} IOPS |\n", disk.random_read_iops));
            content.push_str(&format!("| 隨機寫入 | {:.2} IOPS |\n\n", disk.random_write_iops));
        }
        
        if let Some(net) = &result.network_results {
            content.push_str("## 網路測試結果\n\n");
            content.push_str("| 項目 | 數值 |\n");
            content.push_str("|------|------|\n");
            content.push_str(&format!("| 測試主機 | {} |\n", net.test_host));
            content.push_str(&format!("| 延遲 | {:.2} ms |\n", net.latency_ms));
            content.push_str(&format!("| 下載速度 | {:.2} Mbps |\n", net.download_mbps));
            content.push_str(&format!("| 上傳速度 | {:.2} Mbps |\n", net.upload_mbps));
            content.push_str(&format!("| 封包遺失率 | {:.2}% |\n\n", net.packet_loss_percent));
        }
        
        let mut file = File::create(filename)?;
        file.write_all(content.as_bytes())?;
        
        println!("✅ Markdown 報告已儲存至: {}", filename.green());
        Ok(())
    }
}

main.rs 主程式

mod models;
mod cpu_bench;
mod disk_bench;
mod network_bench;
mod reporter;

use anyhow::Result;
use chrono::Local;
use clap::{Parser, Subcommand};
use std::time::Instant;
use models::BenchmarkResult;
use cpu_bench::CpuBenchmarker;
use disk_bench::DiskBenchmarker;
use network_bench::NetworkBenchmarker;
use reporter::Reporter;

#[derive(Parser)]
#[command(name = "system-benchmark")]
#[command(about = "系統效能基準測試工具", long_about = None)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// 執行 CPU 基準測試
    Cpu {
        /// 測試持續時間(秒)
        #[arg(short, long, default_value = "5")]
        duration: u64,
        
        /// 輸出檔案名稱
        #[arg(short, long)]
        output: Option<String>,
    },
    
    /// 執行磁碟基準測試
    Disk {
        /// 測試檔案路徑
        #[arg(short, long, default_value = "benchmark_test.dat")]
        file: String,
        
        /// 測試檔案大小(MB)
        #[arg(short, long, default_value = "100")]
        size: usize,
        
        /// 輸出檔案名稱
        #[arg(short, long)]
        output: Option<String>,
    },
    
    /// 執行網路基準測試
    Network {
        /// 測試主機位址
        #[arg(short, long, default_value = "www.google.com:80")]
        host: String,
        
        /// 輸出檔案名稱
        #[arg(short, long)]
        output: Option<String>,
    },
    
    /// 執行完整基準測試
    Full {
        /// CPU 測試持續時間(秒)
        #[arg(long, default_value = "5")]
        cpu_duration: u64,
        
        /// 磁碟測試檔案大小(MB)
        #[arg(long, default_value = "100")]
        disk_size: usize,
        
        /// 網路測試主機
        #[arg(long, default_value = "www.google.com:80")]
        network_host: String,
        
        /// 輸出檔案名稱
        #[arg(short, long)]
        output: Option<String>,
        
        /// 同時產生 Markdown 報告
        #[arg(short, long)]
        markdown: bool,
    },
}

#[tokio::main]
async fn main() -> Result<()> {
    let cli = Cli::parse();

    match cli.command {
        Commands::Cpu { duration, output } => {
            run_cpu_benchmark(duration, output).await?;
        }
        Commands::Disk { file, size, output } => {
            run_disk_benchmark(file, size, output).await?;
        }
        Commands::Network { host, output } => {
            run_network_benchmark(host, output).await?;
        }
        Commands::Full {
            cpu_duration,
            disk_size,
            network_host,
            output,
            markdown,
        } => {
            run_full_benchmark(cpu_duration, disk_size, network_host, output, markdown).await?;
        }
    }

    Ok(())
}

async fn run_cpu_benchmark(duration: u64, output: Option<String>) -> Result<()> {
    let start = Instant::now();
    let benchmarker = CpuBenchmarker::new();
    let cpu_results = benchmarker.run_benchmark(duration)?;
    
    let result = BenchmarkResult {
        test_name: "CPU Benchmark".to_string(),
        duration: start.elapsed(),
        timestamp: Local::now().format("%Y-%m-%d %H:%M:%S").to_string(),
        cpu_results: Some(cpu_results),
        disk_results: None,
        network_results: None,
    };
    
    Reporter::print_results(&result);
    
    if let Some(filename) = output {
        Reporter::save_to_file(&result, &filename)?;
    }
    
    Ok(())
}

async fn run_disk_benchmark(file: String, size: usize, output: Option<String>) -> Result<()> {
    let start = Instant::now();
    let benchmarker = DiskBenchmarker::new(file, size);
    let disk_results = benchmarker.run_benchmark()?;
    
    let result = BenchmarkResult {
        test_name: "Disk Benchmark".to_string(),
        duration: start.elapsed(),
        timestamp: Local::now().format("%Y-%m-%d %H:%M:%S").to_string(),
        cpu_results: None,
        disk_results: Some(disk_results),
        network_results: None,
    };
    
    Reporter::print_results(&result);
    
    if let Some(filename) = output {
        Reporter::save_to_file(&result, &filename)?;
    }
    
    Ok(())
}

async fn run_network_benchmark(host: String, output: Option<String>) -> Result<()> {
    let start = Instant::now();
    let benchmarker = NetworkBenchmarker::new(host);
    let network_results = benchmarker.run_benchmark().await?;
    
    let result = BenchmarkResult {
        test_name: "Network Benchmark".to_string(),
        duration: start.elapsed(),
        timestamp: Local::now().format("%Y-%m-%d %H:%M:%S").to_string(),
        cpu_results: None,
        disk_results: None,
        network_results: Some(network_results),
    };
    
    Reporter::print_results(&result);
    
    if let Some(filename) = output {
        Reporter::save_to_file(&result, &filename)?;
    }
    
    Ok(())
}

async fn run_full_benchmark(
    cpu_duration: u64,
    disk_size: usize,
    network_host: String,
    output: Option<String>,
    markdown: bool,
) -> Result<()> {
    println!("🚀 開始完整系統基準測試...\n");
    
    let start = Instant::now();
    
    // CPU 測試
    let cpu_benchmarker = CpuBenchmarker::new();
    let cpu_results = cpu_benchmarker.run_benchmark(cpu_duration)?;
    
    // 磁碟測試
    let disk_benchmarker = DiskBenchmarker::new("benchmark_test.dat".to_string(), disk_size);
    let disk_results = disk_benchmarker.run_benchmark()?;
    
    // 網路測試
    let network_benchmarker = NetworkBenchmarker::new(network_host);
    let network_results = network_benchmarker.run_benchmark().await?;
    
    let result = BenchmarkResult {
        test_name: "Full System Benchmark".to_string(),
        duration: start.elapsed(),
        timestamp: Local::now().format("%Y-%m-%d %H:%M:%S").to_string(),
        cpu_results: Some(cpu_results),
        disk_results: Some(disk_results),
        network_results: Some(network_results),
    };
    
    Reporter::print_results(&result);
    
    if let Some(filename) = output {
        Reporter::save_to_file(&result, &filename)?;    
        if markdown {
            let md_filename = filename.replace(".json", ".md");
            Reporter::generate_markdown_report(&result, &md_filename)?;
        }
    }Ok(())
}

開始使用

## 使用範例

### 1. 執行 CPU 測試
```bash
# 基本 CPU 測試
cargo run -- cpu

# 指定測試時間並儲存結果
cargo run -- cpu --duration 10 --output cpu_results.json

# 基本磁碟測試
cargo run -- disk

# 自訂測試檔案和大小
cargo run -- disk --file /tmp/test.dat --size 500 --output disk_results.json

# 基本網路測試
cargo run -- network

# 測試特定主機
cargo run -- network --host "example.com:443" --output network_results.json

完整測試

# 執行所有測試
cargo run -- full

# 完整測試並產生報告
cargo run -- full --output full_results.json --markdown

# 自訂所有參數
cargo run -- full \
  --cpu-duration 10 \
  --disk-size 200 \
  --network-host "www.google.com:80" \
  --output benchmark.json \
  --markdown

額外補充

仿間有各種 lib 其實可以實現個人目標,也可以視為值得參考的部分


上一篇
程序管理器 - 管理和監控後台程序
下一篇
個人任務管理 API - 完整的 RESTful 待辦事項服務
系列文
Rust 實戰專案集:30 個漸進式專案從工具到服務28
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言