PHP 陣列底層為雜湊表,記憶體效率極低(約 1/10)。對於大量數值型資料,可使用 pack()/unpack() 以二進位字串儲存,大幅減少記憶體佔用。
memory_limit 限制<?php
$count = 100000;
$binaryString = '';
// 寫入:以 double 格式打包
for ($i = 0; $i < $count; $i++) {
$binaryString .= pack('d', $i + 0.1); // 每個 8 bytes
}
// 讀取:按位移解包
for ($i = 0; $i < $count; $i++) {
$value = unpack('@' . ($i * 8) . '/d', $binaryString);
// $value[1] 即為第 $i 個數值
}
// 記憶體佔用:約 800 KB(vs 陣列 48 MB+)
echo '字串長度: ' . strlen($binaryString) . ' bytes'; // 800,000
?>
class BinaryDoubleArray {
private string $buffer = '';
private int $count = 0;
private const ITEM_SIZE = 8; // double = 8 bytes
public function append(float $value): void {
$this->buffer .= pack('d', $value);
$this->count++;
}
public function get(int $index): float {
if ($index < 0 || $index >= $this->count) {
throw new OutOfBoundsException("Index $index out of range");
}
$data = unpack('@' . ($index * self::ITEM_SIZE) . '/d', $this->buffer);
return $data[1];
}
public function count(): int {
return $this->count;
}
public function memoryUsage(): int {
return strlen($this->buffer);
}
// 批次讀取(效能較佳)
public function getRange(int $offset, int $length): array {
$format = '@' . ($offset * self::ITEM_SIZE) . '/' . str_repeat('d', $length);
return array_values(unpack($format, $this->buffer));
}
}
// 使用範例
$arr = new BinaryDoubleArray();
for ($i = 0; $i < 100000; $i++) {
$arr->append($i * 1.5);
}
echo "記憶體: {$arr->memoryUsage()} bytes\n"; // ~800KB
echo "第 50000 個: " . $arr->get(50000) . "\n"; // 75000
?>
| 適用 | 不適用 |
|---|---|
| 大量數值型資料(float/int) | 字串、物件、混合型別 |
| 順序讀取、隨機存取 | 頻繁插入/刪除中間元素 |
| 記憶體受限環境 | 需關聯式鍵值存取 |
| 暫存計算中間結果 | 長期持久化(建議用資料庫) |
此技巧適合「寫一次、讀多次、記憶體敏感」的數值密集型場景,如科學計算、日誌分析、大量感測器資料暫存。