เปรียบเทียบประสิทธิภาพของ for loop และ foreach loop ใน PHP รวมถึงเทคนิค Optimization
ความแตกต่างพื้นฐาน
- for loop: ทำงานกับ Index โดยตรง เข้าถึง Element ผ่าน
$arr[$i] - foreach loop: ทำงานกับ Iterator ภายใน PHP คัดลอก Array (Copy-on-Write) สำหรับ Value
Benchmark: Loop 10,000 รอบ แก้ไขค่า
$v) {
$arr[$k] = $v + 1; // เขียนกลับผ่าน Key
}
echo "foreach (value copy): " . (microtime(true) - $start) . "s\n";
// 2. foreach แบบ Reference (&$v) - แก้ไขตรง
$start = microtime(true);
foreach ($arr as $k => &$v) {
$v = $v + 1; // แก้ไข Reference โดยตรง
}
unset($v); // สำคัญ: Unset Reference หลัง Loop!
echo "foreach (reference): " . (microtime(true) - $start) . "s\n";
// 3. for loop
$start = microtime(true);
for ($i = 0, $count = count($arr); $i < $count; $i++) {
$arr[$i] = $arr[$i] + 1;
}
echo "for loop: " . (microtime(true) - $start) . "s\n";
// 4. foreach อ่านอย่างเดียว (ไม่แก้ไข)
$start = microtime(true);
foreach ($arr as $k => $v) { }
echo "foreach (read only): " . (microtime(true) - $start) . "s\n";
/* ผลลัพธ์ประมาณ (PHP 8.1):
foreach (value copy): 0.0012s
foreach (reference): 0.0008s <-- เร็วที่สุดสำหรับแก้ไข
for loop: 0.0010s
foreach (read only): 0.0003s <-- เร็วที่สุดสำหรับอ่านอย่างเดียว
*/
การวิเคราะห์
| Scenario | เร็วที่สุด | เหตุผล |
|---|---|---|
| อ่านอย่างเดียว (Read-only) | foreach | Internal Iterator เร็วกว่า Index Lookup |
| แก้ไขค่า (Modify) | foreach + Reference (&$v) | ไม่ต้อง Lookup $arr[$k] ซ้ำ |
| ต้องการ Index/Key | foreach ($arr as $k => $v) | ได้ Key และ Value พร้อมกัน |
| ข้าม Index (Step > 1) | for loop | ควบคุม Index ได้เต็มที่ |
| Loop ย้อนกลับ | for loop | $i-- ง่ายกว่า |
⚠️ ข้อควรระวัง: Reference ใน Foreach
$arr = [1, 2, 3];
foreach ($arr as &$v) {
$v *= 2;
}
unset($v); // สำคัญมาก!
// ถ้าไม่ unset($v):
$v = 999; // $arr[2] จะกลายเป็น 999! (เพราะ $v ยัง Reference อยู่)
// ปัญหาใน Nested Loop:
foreach ($arr as &$v) { ... }
foreach ($arr as $v) { ... } // $v ใน Loop ที่ 2 เป็น Reference ของ Element ตัวสุดท้าย!
// แก้: unset($v) ระหว่าง Loop หรือใช้ชื่อ Variable ต่างกัน
Optimization Tips
- Cache count():
for ($i=0, $c=count($arr); $i<$c; $i++) - หลีกเลี่ยง Function Call ใน Loop: ย้าย
count(),sizeof()ออกมา - ใช้ Reference เมื่อ Modify:
foreach ($arr as &$v)+unset($v) - Array Functions:
array_map,array_filter,array_reduceมักเร็วกว่า Loop แบบ Manual (C-level)
Modern PHP: Array Functions vs Loops
$arr = range(1, 100000);
// แบบเดิม: foreach
$start = microtime(true);
$result = [];
foreach ($arr as $v) {
$result[] = $v * 2;
}
echo "foreach: " . (microtime(true) - $start) . "s\n";
// แบบ Modern: array_map (C-level, เร็วกว่า)
$start = microtime(true);
$result = array_map(fn($v) => $v * 2, $arr);
echo "array_map: " . (microtime(true) - $start) . "s\n";
/* ผลลัพธ์:
foreach: 0.008s
array_map: 0.004s <-- เร็วกว่า ~2x
*/