GORAGOD.com

เขียนโค้ดอย่างไรให้ประมวลผลได้เร็วและมีประสิทธิภาพสูงที่สุด

การเขียนโค้ดที่ดี นอกจากจะต้องอ่านง่ายแล้ว ยังต้องเขียนโค้ดให้ประมวลผลได้เร็วด้วย ยิ่งโค้ดของเราช้าเท่าไรประสิทธิภาพของแอพพลิเคชั่นของเราก็จะน้อยลง ส่งผลให้ที่ Server ขนาดเดียวกัน จะรับผู้เยี่ยมชมพร้อมๆกันได้น้อยกว่า (Concurrency) หรืออาจต้องใช้ Server ที่มีประสิทธิภาพ(และค่าใช้จ่าย)สูงกว่ามาใช้งาน

ออกจาก Framework เหอะ เพราะมันช้า คงไม่มีใครเปฏิเสธนะว่าการเขียน PHP แบบธรรมดามันเร็วกว่าการใช้ Framework อยู่พอสมควร ยิ่ง Framework ที่มีความสามารถสูงๆ มันก็ต้องยิ่งช้า เพราะมันมีหลายสิ่งอย่างที่ต้องทำก่อนจะประมวลผลจริง หรือ ถ้าต้องการเขียนโค้ดในรูปแบบ MVC จริงๆ (ไม่ว่าจะด้วยหตุผลใดๆก็ตาม) ผมแนะนำ Micro Framework เลยมันช้ากว่าเขียน PHP ปกตินิดหน่อย แต่ก็ช่วยให้เขียนได้เป็นระเบียบมากขึ้นตามรูปแบบ MVC

โค้ด PHP ที่เราเขียน มันจะมีวิธีที่ดีที่สุด อยู่เพียง 1 วิธีเสมอ เราต้องตรวจสอบด้วยตัวเองว่า โค้ดที่เราเขียนดีที่สุดหรือยัง วิธีการทดสอบว่าโค้ดดีที่สุดแล้วหรือยังคือการทำ benchmark ยิ่งเรามีโอกาสได้ทดสอบ benchmark ที่เราเขียนได้มากเท่าไร มันจะยิ่งเป็นประสบการณ์สำหรับการเขียนที่ดีต่อไปในอนาคต เพราะในอนาคตเราสามารถเลือกเขียนวิธีที่ดีที่สุดได้จากประสบการณ์
โค้ดที่ดีที่สุด มักจะเป็นโค้ดที่สั้นที่สุด ซึ่งจะทำให้การอ่านหรือดูแลรักษาในระยะยาวทำได้ง่าย
ฟังก์ชั่นของ PHP ไม่ได้เร็วกว่าเสมอไป มีหลายฟังก์ชั่นที่ผมเคยทดสอบ benchmark แล้วพบว่าการใช้ PHP ที่เขียนเองเร็วกว่า เหตุผล ก็เพราะว่า ในบางฟังก์ชั่นที่มีความสามารถสูงๆ PHP จะต้องทำการตรวจสอบตัวแปรก่อนการประมวลผล ซึ่งหากตัวแปรที่จะส่งให้กับฟังก์ชั่นมันชัดเจนถูกต้องอยู่แล้วก็ไม่จำเป็นต้องทดสอบอีก ทำให้การเขียนคำสั่ง PHP สั้นๆทดแทนประมวลผลได้เร็วกว่า
ยกตัวอย่างฟังก์ชั่น array_merge ของ PHP ที่ผมเคยทำการทดสอบไว้ เปรียบเทียบความเร็วของฟังก์ชั่น array_merge และการผสานแอเรย์ด้วย PHP

เขียนเป็นฟังก์ชั่น ช้ากว่าเขียนคำสั่งลงในโค้ดตรงๆ นะ อันนี้ก็เป็นเรื่องปกติ ยกตัวอย่างเช่นคำสั่งทดแทน array_merge ในหัวข้อก่อนหน้า หากนำคำสั่งที่ใช้มาสร้างเป็นฟังก์ชั่นเพื่อจะให้สามารถใช้ซ้ำได้ จะมีผลให้การประมวลผลช้าลงจนอาจจะเทียบเท่ากับการใช้ฟังก์ชั่นของ PHP ได้เลยทีเดียว เพราะการเรียกใช้ฟังก์ชั่น PHP จะต้องมีการทำงานเพิ่มเติมอีกหลายอย่าง เพื่อที่จะใช้งานฟังก์ชั่น คำแนะนำคือ benchmark นั่นแหละครับ รูปแบบไหนเร็วที่สุดให้ใช้แบบนั้น เช่น คำสั่งสั้นๆแค่ไม่กี่บรรทัดแต่เร็วที่สุด ก็ใช้อันนั้น หรือ ถ้าเขียนเป็นฟังก์ชั่นแล้วมันช้ากว่าฟังก์ชั่นของ PHP ก็ใช้ฟังก์ชั่นของ PHP

เส้นทางเดินของโค้ดต้องสั้นที่สุด อันนี้เป็นสาเหตุหลักเลยที่ทำให้การเขียนโค้ดรูปแบบ PHP ธรรมดาเร็วกว่าการใช้ Framework และถึงแม้เราจะเขียนด้วย PHP ธรรมดาเราก็ยังคงต้องทำให้มันสั้นที่สุดอยู่ดี โค้ดที่ทำงานเหมือนๆกันทุกประการแต่จำนวนบรรทัดน้อยกว่าจะมีแนวโน้มว่าจะเร็วกว่า (อย่าลืมรวมโค้ดของ Framework ที่ใช้ด้วยนะครับ)

เคยทดสอบความเร็วของคำสั่ง SQL หรือไม่ การใช้งานฐานข้อมูลก็เป็นอีกสาเหตุหลักที่ทำให้แอพพลิเคชั่นช้า โดยเฉพาะในอนาคตที่ขนาดของฐานข้อมูลใหญ่ขึ้นมันก็จะต้องช้าลง ทุกๆคำสั่งที่เรากระทำกับฐานข้อมูลจะมี 1 วิธีที่เร็วที่สุดเสมอเช่นกัน ซึ่งถ้าเราหมั่นตรวจสอบ ทดสอบ และ benchmark เราก็จะสามารถเลือกวิธีที่เหมาะสมได้ในอนาคตเช่นกัน
โปรแกรมสำหรับการตรวจสอบความเร็วของคำสั่ง SQL ผมใช้ Neor Profile SQL โปรแกรมตรวจสอบการทำงานของ MySQL

ใช้ Index ให้ถูกที่ถุกเวลา ยังอยู่ที่เรื่องของฐานข้อมูลนะครับ การค้นหา การ JOIN จะเร็วที่สุดเมื่อมีการค้นหาข้อมูลบนคอลัมน์ที่เป็น Index (ศึกษาเรื่องการใช้ Index ให้ถูกต้องก่อนการใช้งานด้วยนะครับ) แต่ข้อเสียของ Index จะทำให้การ INSERT UPDATE และ DELETE ข้อมูลช้าลง เนื่องจากทุกการกระทำที่เกิดขึ้น จะมีการอัปเดท Index เสมอ
หลายๆคนอาจยังไม่ทราบว่า 
  • เราสามารถมี Index ได้มากกว่า 1 รายการเช่น นอกจาก id ที่มันจะเป็น Index แล้ว ยังเป็น Key ด้วย (Key หมายถึงมันจะไม่สามารถมีค่าซ้ำได้) โดยคอลัมน์ที่ควรจะทำ Index ก็คือคอลัมน์ที่จะใช้ในการค้นหา เช่น คอลัมน์ username
  • คอลัมน์ที่ต้องใช้การค้นหาร่วมกัน (มากกว่า 1 คอลัมน์) เสมอ สามารถทำ Index ร่วมกันทั้งสองคอลัมน์ได้ เช่น customer_id และ category_id จะต้องค้นหาร่วมกันเสมอ เราสามารถรวมทั้งสองคอลัมน์ให้เป็น Index รายการเดียวอีกรายการได้ ถึงแม้ว่าเราจะทำ Index ให้กับ customer_id และ category_id อยู่แล้ว
  • ลำดับของคอลัมน์ในรายการที่ใช้เป็น Index ร่วมกันจะต้องเรียงลำดับให้ถูกต้องด้วย เพราะถ้าเรียงลำดับไม่ถูกต้องจะทำให้ได้ Index ที่มีขนาดใหญ่กว่าที่ควรจะเป็น และ อาจไม่สามารถใช้ความสามารถของ Index ที่ต้องการได้อย่างมีประสิทธิภาพ
  • SEARCH% สามารถใช้ความสามารถของ Index ได้ แต่ %SEARCH% ไม่สามารถใช้ความสามารถของ Index ในการค้นหาได้ ถ้าคอลัมน์ที่ค้นหาเป็น Index

จะใช้ PHP ร่วมกับคำสั่ง SQL หรือใช้คำสั่ง SQL ล้วนๆ วิธีไหนจะเหมาะสมกว่าไม่มีใครตอบแทนได้ เพราะมีปัจจัยประกอบหลายอย่าง ตั้งแต่รูปแบบ SQL ตัวฐานข้อมูลเองมีความเหมาะสมหรือไม่ ตลอดจนผลลัพท์ที่ต้องการ แต่สิ่งที่ควรทำคือ
  • ลดการใช้คำสั่งของ SQL ในการคำนวณ หากผลการคำนวณใช้เพื่อแสดงผลเฉยๆ โดยให้ใช้ PHP ในการประมวลผลเพื่อแสดงผลแทน เนื่องจากคำสั่งคำนวณจะทำให้ SQL ประมวลผลได้ช้าลง และโดยหลักการแล้วเราควรลดการประมวลผลบน SQL Server ลงให้เหลือน้อยที่สุด
  • เก็บเฉพาะข้อมูลดิบใช่ว่าจะดีกว่าเสมอไป จริงอยู่ว่าการเก็บข้อมูลดิบจะทำให้เราสามารถนำข้อมูลไปประยุกต์ใช้งานต่อได้ง่าย แต่การประมวลผลข้อมูลบางอย่างเพิ่มเติม (ในกรณีที่ทำได้) สามารถลดกระบวนการสรุปข้อมูลในภายหลังได้
  • เลือกวิธีที่เหมาะสมในการจัดเก็บข้อมูลด้วยตัวเอง อย่าไปเชื่อ best particle มากนัก เพราะ best particle จริงๆมันเหมาะสมกับสถานะการณ์แต่ละอัน แตกต่างกัน โดยวิธีที่เหมาะสมที่สุดคือ
    • ควรจัดเก็บได้ง่าย
    • ควรใช้งานได้ง่าย หรือนำไปใช้ต่อได้ง่าย และเขียน Query ได้ไม่ซับซ้อน
    • สามารถ Query ได้รวดเร็ว
  • อย่าลืม benchmark ว่าการใช้ PHP ร่วมกับคำสั่ง SQL หรือใช้คำสั่ง SQL ล้วนๆ แบบไหนจะมีประสิทธิภาพมากกว่ากัน

ใช้งานแคช นอกจากการเขียนโค้ดและฐานข้อมูลที่ต้องเขียนให้มีประสิทธิภาพแล้ว การใช้งานแคชที่เหมาะสมก็เป็นจุดที่เพิ่มความสามารถได้ (และได้ผลดีที่สุดด้วย) ซึ่งการแคชเองก็มีหลายแบบ เช่น
  • แคชหน้าเว็บ เหมาะกับหน้าเว็บที่ไม่ค่อยมีอะไรเปลี่ยนแปลง ถ้าออกแบบแคชดีๆ แทบจะไม่ต้องประมวลผลอะไรเลยหากมีการเรียกใช้แคช
  • แคชฐานข้อมูล ก็ตามชื่อแหละครับ เป็นการลดการประมวลผลฐานข้อมูลในกรณีที่ผลลัพท์ที่ต้องการไม่ค่อยมีอะไรเปลี่ยนแปลง
ส่วนวิธีการแคชก็มีหลายแบบ เช่น
  • แคชในหน่วยความจำ อันนี้จะเร็วที่สุด เพราะหน่วยตวามจำเป็นส่วนที่เร็วที่สุด
  • แคชเป็นไฟล์ ข้อดีคือประหยัดหน่วยความจำ สามารถนำหน่วยความจำไปใช้ประมวลผลอื่นได้ แต่ก็อย่างว่าแหละ มันช้ากว่าแบบใช้หน่วยความจำ
ข้อดีของแคช คือ ความเร็วในการใช้งาน ในมุมมองของ User แต่แคชเป็นตัวปัญหาของ Dev เพราะไอ้ความสามารถในการจำนี่แหละ ที่ทำให้ Dev ปวดหัวอยู่เสมอ เพราะการเปลี่ยนแปลงใดๆที่ Dev ทำ ต้องไปเคลียร์แคชก่อนเสมอ Dev ถึงจะเห็นการเปลี่ยนแปลงนั้นๆ

สุดท้าย ถ้าเรามั่นใจว่าการเขียนโค้ดของเรามีประสิทธิภาพที่สุดแล้วมันยังไม่เพียงพอ ขั้นตอนต่อไปคือการอัปเกรด Server แล้ว ซึ่งเป็นสิ่งที่ไม่สามารถหลีกเลี่ยงได้ (หรือไม่ก็เปลี่ยนไปใช้ภาษาอื่นในการเขียน ที่มีประสิทธิภาพดีกว่า)