在優化伺服器儲存效能、排查 I/O 瓶頸、驗證雲端磁碟規格時,需要一個簡單、可重現的磁碟寫入基準測試。本文提供一個 PHP 腳本,以 1GB 檔案連續寫入測試順序寫入速度,並說明結果解讀與專業工具對比。
<?php
/**
* 磁碟順序寫入速度測試
* 建立 1GB 暫存檔,測試連續寫入吞吐量
*/
function disk_write_benchmark(
string $target_dir = sys_get_temp_dir(),
int $total_bytes = 1073741824, // 1 GB = 1024^3
int $chunk_size = 512 * 1024 // 512 KB 寫入塊
): array {
// 檢查目錄可寫
if (!is_writable($target_dir)) {
throw new RuntimeException("目錄不可寫: $target_dir");
}
$test_file = $target_dir . '/disk_bench_' . uniqid() . '.tmp';
$pattern = str_repeat('X', $chunk_size); // 512KB 測試資料塊
$handle = fopen($test_file, 'wb');
if (!$handle) {
throw new RuntimeException("無法建立測試檔案: $test_file");
}
echo "開始測試: 目標 {$total_bytes} bytes, 區塊 {$chunk_size} bytes\n";
$start = microtime(true);
$written = 0;
while ($written < $total_bytes) {
$remaining = $total_bytes - $written;
$len = min($chunk_size, $remaining);
$n = fwrite($handle, $pattern, $len);
if ($n === false || $n !== $len) {
fclose($handle);
@unlink($test_file);
throw new RuntimeException("寫入失敗 at $written bytes");
}
$written += $n;
}
// 強制刷新到實體磁碟 (繞過 OS 快取)
fflush($handle);
if (function_exists('fdatasync')) {
fdatasync($handle); // Linux: 僅同步資料
} else {
fsync($handle); // 通用: 同步資料+中繼資料
}
$end = microtime(true);
fclose($handle);
// 清理測試檔
@unlink($test_file);
$elapsed = $end - $start;
$mb_sec = ($total_bytes / 1024 / 1024) / $elapsed;
return [
'total_bytes' => $total_bytes,
'elapsed_sec' => round($elapsed, 3),
'throughput_mb_sec' => round($mb_sec, 2),
'chunk_size' => $chunk_size,
'test_file' => $test_file,
];
}
// === 執行測試 ===
try {
// 可調整測試目錄 (掛載點)、大小、區塊
$result = disk_write_benchmark('/tmp', 1073741824, 524288);
echo "\n=== 測試結果 ===\n";
echo "總資料量: " . number_format($result['total_bytes'] / 1024 / 1024, 0) . " MB\n";
echo "耗時: {$result['elapsed_sec']} 秒\n";
echo "順序寫入速度: {$result['throughput_mb_sec']} MB/s\n";
// 簡易評級
$speed = $result['throughput_mb_sec'];
if ($speed > 500) $grade = '極快 (NVMe SSD / RAM Disk)';
elseif ($speed > 200) $grade = '優秀 (SATA SSD / 高階 NVMe)';
elseif ($speed > 80) $grade = '良好 (SATA SSD / 企業級 HDD RAID)';
elseif ($speed > 30) $grade = '一般 (消費級 HDD)';
else $grade = '較慢 (虛擬化/網路儲存/老舊 HDD)';
echo "評級: $grade\n";
} catch (Exception $e) {
echo "測試失敗: " . $e->getMessage() . "\n";
}
?>
| 參數 | 建議值 | 影響 |
|---|---|---|
$total_bytes | 1 GB (1073741824) | 過小受 OS 快取影響大;過久佔用頻寬。1GB 足以反映持續寫入能 |
$chunk_size | 512 KB ~ 4 MB | 太小系統呼叫開銷大;太大佔用 PHP 記憶體。512KB 平衡。 |
fdatasync/fsync | 必須呼叫 | 不呼叫只測「寫入頁面快取」速度,非實體磁碟速度。 |
| 測試目錄 | 掛載點根目錄 | 避免檔案系統壓縮/去重/快照干擾。 |
| 儲存類型 | 典型順序寫入 (MB/s) | 備註 |
|---|---|---|
| DDR4 RAM Disk | 5,000 - 15,000 | 受限於 CPU/記憶體頻寬 |
| NVMe SSD (PCIe 4.0) | 3,000 - 7,000 | 消費級 3.5-5GB/s,企業級更高 |
| NVMe SSD (PCIe 3.0) | 1,500 - 3,500 | |
| SATA SSD | 400 - 550 | 受限於 SATA 6Gbps (理論 600 MB/s) |
| 企業級 HDD (15K RPM, RAID 10) | 300 - 600 | 隨機寫入差距極大 |
| 消費級 HDD (7200 RPM) | 100 - 200 | 外接 USB 3.0 可達 150-180 |
| 網路儲存 (iSCSI/NFS 1GbE) | 80 - 110 | 受網路頻寬限制 |
| 虛擬化共享儲存 | 20 - 100 | 受超售、快照、QoS 影響大 |
順序寫入無法反映資料庫、日誌、虛擬機等隨機 I/O 負載。專業測試請使用:
fio --name=randwrite --ioengine=libaio --rw=randwrite --bs=4k --size=1G --numjobs=4 --iodepth=32 --runtime=60 --group_reportingsysbench fileio --file-total-size=1G --file-test-mode=rndwr runstr_repeat('X')) 會被去重,導致寫入量極小、速度虛高。解決:使用隨機資料 random_bytes($chunk_size) 或關閉壓縮。memory_limit 需 > $chunk_size,建議 512MB 以上。本腳本提供一個「開箱即用、結果可信」的 PHP 磁碟順序寫入基準測試。關鍵在於 足夠大的測試檔 (1GB+)、適當區塊大小 (512KB)、強制 fdatasync 刷新到實體磁碟、使用隨機資料避免去重。結果可作為採購驗收、遷移驗證、效能基準的參考;關鍵業務系統仍建議搭配 fio 進行全方位 IOPS/延遲/穩定性測試。