เปรียบเทียบความเร็วในการแปลตัวเลข 0-9 ให้เป็นภาษาอังกฤษ
โจทย์ต้องการแปลตัวเลข 0-9 ให้เป็นภาษาอังกฤษ ส่วนตัวเลขอื่นๆ นอกจากนี้ให้คืนค่าตัวเลขออกมา โดยแสดงผลบนบราวเซอร์ (PHP)
จากโจทย์ หลายคนคงคิดถึง if และ switch case ประมาณนี้
โดยการใช้ if else
หรือการใช้ switch case
ซึ่งโดยทั่วๆ เราจะมองว่ามันเป็นคำสั่งพื้นฐาน
ในแง่ความเร็ว หลายๆคนคงเคยได้ยินมาว่า switch case นั้นเร็วกว่า if else ซึ่งจากการที่ผมทดสอบมันก็เป็นแบบนั้นแหละ แต่มันมีปัญหาอยู่อย่างหนึงของการใช้ if else และ switch case คือในกรณีที่เงื่อนไขมันมากคำสั่งก็จะยาวและอ่านยากไปด้วยตามมา (ดูได่จากโค้ดด้านล่าง) แล้วจะมีวิธีไหนที่จะลดความซับซ้อนของโค้ดลงได้
ผมขอเสนออีกวิธีหนึ่ง ด้วยการใช้ isset
โค้ดด้านบนเราจะสร้างแอเรย์เก็บ ตัวเลข 0-9 พร้อมกับคำแปลตามโจทย์ จากนั้นใช้ isset ในการทดสอบว่ามีตัวแปรที่ต้องการหรือไม่ ถ้ามีก็คืนค่าตัวแปรนั้นๆ ออกมา โค้ดสั้นและง่ายขึ้นเห็นๆ (คำสั่งแอเรย์ที่สร้างอาจดูยาวอยู่นะครับ แต่มันก็อ่านง่าย รวมถึงแก้ไขง่ายขึ้นเยอะเลย) ส่วนความเร็วของคำสั่งทั้งสามรูปแบบ ดูได้ท้ายบทความเลย (สามารถนำโค้ดไปทดสอบได้ในเครื่องตัวเอง)
ผลการทดสอบ Benchmark ของคำสั่งแต่ละรูปแบบ
จากโจทย์ หลายคนคงคิดถึง if และ switch case ประมาณนี้
โดยการใช้ if else
if ($value == 0) {
echo "Zero\n";
} elseif ($value == 1) {
.....
} else {
// ไม่พบ
echo $value."\n";
}
หรือการใช้ switch case
switch ($value) {
case 0:
echo "Zero\n";
break;
case 1:
.....
default:
// ไม่พบ
echo $value."\n";
break;
}
ซึ่งโดยทั่วๆ เราจะมองว่ามันเป็นคำสั่งพื้นฐาน
ในแง่ความเร็ว หลายๆคนคงเคยได้ยินมาว่า switch case นั้นเร็วกว่า if else ซึ่งจากการที่ผมทดสอบมันก็เป็นแบบนั้นแหละ แต่มันมีปัญหาอยู่อย่างหนึงของการใช้ if else และ switch case คือในกรณีที่เงื่อนไขมันมากคำสั่งก็จะยาวและอ่านยากไปด้วยตามมา (ดูได่จากโค้ดด้านล่าง) แล้วจะมีวิธีไหนที่จะลดความซับซ้อนของโค้ดลงได้
ผมขอเสนออีกวิธีหนึ่ง ด้วยการใช้ isset
// ตัวแปรแอเรย์เก็บตัวเลขในภาษาอังกฤษ
$numbers = array(
0 => 'Zero',
1 => 'One',
....
9 => 'Nine',
);
if (isset($numbers[$value])) {
// พบ
echo $numbers[$value]."\n";
} else {
// ไม่พบ
echo $value."\n";
}
โค้ดด้านบนเราจะสร้างแอเรย์เก็บ ตัวเลข 0-9 พร้อมกับคำแปลตามโจทย์ จากนั้นใช้ isset ในการทดสอบว่ามีตัวแปรที่ต้องการหรือไม่ ถ้ามีก็คืนค่าตัวแปรนั้นๆ ออกมา โค้ดสั้นและง่ายขึ้นเห็นๆ (คำสั่งแอเรย์ที่สร้างอาจดูยาวอยู่นะครับ แต่มันก็อ่านง่าย รวมถึงแก้ไขง่ายขึ้นเยอะเลย) ส่วนความเร็วของคำสั่งทั้งสามรูปแบบ ดูได้ท้ายบทความเลย (สามารถนำโค้ดไปทดสอบได้ในเครื่องตัวเอง)
// จำนวนรอบการทดสอบ ผลลัพท์เฉลี่ยจากค่านี้
$count = 100;
// แอเรย์เก็บผลลัพท์
$ret = array(0, 0, 0);
// ตัวเลขที่ต้องการแปล 0 - 11
$wants = range(0, 11);
// ตัวแปรแอเรย์เก็บตัวเลขในภาษาอังกฤษ
$numbers = array(
0 => 'Zero',
1 => 'One',
2 => 'Two',
3 => 'Three',
4 => 'Four',
5 => 'Five',
6 => 'Six',
7 => 'Seven',
8 => 'Eight',
9 => 'Nine',
);
for ($m = 0; $m < $count; $m++) {
$start = microtime(true);
foreach ($wants as $value) {
if (isset($numbers[$value])) {
// คืนค่าตัวเลขในภาษาอังกฤษ
echo $numbers[$value]."\n";
} else {
// ไม่พบ
echo $value."\n";
}
}
$ret[0] += microtime(true) - $start;
}
usleep(10240);
for ($m = 0; $m < $count; $m++) {
$start = microtime(true);
foreach ($wants as $value) {
if ($value == 0) {
echo "Zero\n";
} elseif ($value == 1) {
echo "One\n";
} elseif ($value == 2) {
echo "Two\n";
} elseif ($value == 3) {
echo "Three\n";
} elseif ($value == 4) {
echo "Four\n";
} elseif ($value == 5) {
echo "Five\n";
} elseif ($value == 6) {
echo "Six\n";
} elseif ($value == 7) {
echo "Seven\n";
} elseif ($value == 8) {
echo "Eight\n";
} elseif ($value == 9) {
echo "Nine\n";
} else {
// ไม่พบ
echo $value."\n";
}
}
$ret[1] += microtime(true) - $start;
}
usleep(10240);
for ($m = 0; $m < $count; $m++) {
$start = microtime(true);
foreach ($wants as $value) {
switch ($value) {
case 0:
echo "Zero\n";
break;
case 1:
echo "One\n";
break;
case 2:
echo "Two\n";
break;
case 3:
echo "Three\n";
break;
case 4:
echo "Four\n";
break;
case 5:
echo "Five\n";
break;
case 6:
echo "Six\n";
break;
case 7:
echo "Sever\n";
break;
case 8:
echo "Eight\n";
break;
case 9:
echo "Nine\n";
break;
default:
echo $value."\n";
break;
}
}
$ret[2] += microtime(true) - $start;
}
usleep(10240);
echo '<br><br>Current PHP version: '.phpversion().'<br>';
echo ($ret[0] / $count).' (isset)<br>';
echo ($ret[1] / $count).' (if else)<br>';
echo ($ret[2] / $count).' (switch case)<br>';
ผลการทดสอบ Benchmark ของคำสั่งแต่ละรูปแบบ
- ผลการทดสอบเฉลี่ยผมให้ isset ชนะ ทั้งในแง่อ่านง่ายแก้ไขง่าย และทางด้านความเร็ว
- ผลการทดสอบจริงอาจแตกต่างจากนี้เนื่องจากเวอร์ชั่นของ PHP (PHP แต่ละเวอร์ชั่นอาจได้ผลลัพท์แตกต่างจากนี้ เนื่องจากการ Optimize ของ PHP เอง)
- ผลการทดสอบในแต่ละรอบไม่ได้ให้ผลเหมือนกันทุกครั้ง และ isset ไมได้เร็วกว่า switch case ซะทุกครั้ง โดยมี if else รั้งท้าย หากใครต้องการเห็นผลทดสอบจริงๆ แนะนำให้นำโค้ดไปรันทดสอบบนเครื่องตัวเอง
- การทดสอบในตัวอย่าง กระทำกับแต่ละคำสั่งเป็นจำนวน 100 รอบ (ดูได้จากโค้ด) แล้วคืนค่าเวลาเฉลี่ยของแต่ละรูปแบบออกมา