ทำไมภาษา Programming นึง ถึงเร็วกว่าอีกภาษานึง
By Arnon Puitrakul - 24 กรกฎาคม 2025
เราอาจจะเห็นกลุ่มโปรแกรมมิ่งพูดเรื่องว่า ภาษา Programming อันนึงเร็วกว่าอีกภาษานึง เช่นบอกว่า C เร็วกว่า Python งั้นทำไมเราไม่ไปใช้ C กับทุกอย่างเลยละ วันนี้เราเลยอยากจะมาเล่าให้อ่านกันว่า ทำไมภาษานึงถึงเร็วกว่าอีกภาษานึง
เครื่องคอมพิวเตอร์ไม่เข้าใจภาษา Programming
เราต้องมาทำความเข้าใจกันก่อนว่า จริง ๆ แล้วเครื่องคอมพิวเตอร์ไม่เข้าใจภาษา Programming เลย แต่เครื่องคอมพิวเตอร์เข้าใจแค่ภาษาเดียวที่เรียกว่า Machine Code ที่ประกอบด้วยเพียงแค่เลข 0 และ 1 เท่านั้น บอกเลยว่า ด้วยความซับซ้อนของ Software ปัจจุบัน เป็นไปได้ยากมาก ๆ ที่เราจะเขียนมันด้วย Machine Code แน่ ๆ
ดังนั้น มันจะต้องมีกระบวนการอะไรบางอย่าง เพื่อที่เราจะสามารถแปลงภาษาที่เราเข้าใจ ให้กลายเป็น Machine Code ที่เครื่องเข้าใจ
Compiler
การที่เราจะแปลง Source Code ให้กลายเป็น Machine Code เราจะต้องใช้โปรแกรมที่เรียกว่า Compile ตัวอย่างของมันที่เราใช้งานบ่อย ๆ คือ gcc ที่เป็น C Compiler ที่แค่เรา C Source Code ไปรันผ่าน gcc เราก็จะได้ออกมาเป็น Executable File สำหรับเอาไปรันในเครื่องของเราได้ทันที หากเราเอา Executable File นี้แยกออกมา เราจะประกอบด้วย 5 ส่วนใหญ่ ๆ เช่นกัน
- Header ที่ทำหน้าที่เก็บข้อมูลที่เกี่ยวข้องกับโปรแกรมนั้น ๆ เช่น ชื่อโปรแกรม
- Import/Export Table เก็บพวกข้อมูล Function ว่ามันควรจะไปเรียกใคร หรือ ถูกเรียกอะไรได้บ้าง เพราะบางครั้ง เราสามารถไปดึงส่วนประกอบจากโปรแกรมอื่น ๆ ได้
- Resource เก็บพวก String, Image และ Icon ต่าง ๆ ที่เราใช้งานในโปรแกรม
- Data เก็บพวก ตัวแปร และค่าคงที่ต่าง ๆ ที่มีการประกาศ Hard Code เข้าไปในโปรแกรม
- Executable Code ส่วนนี้แหละ ส่วนสำคัญเลยคือ ส่วนที่เก็บชุดคำสั่งของโปรแกรมตามที่มีการเขียน และถูก Compile เอาไว้
โดยที่ Scheme ในการเก็บส่วนต่าง ๆ นั้นจะมีความแตกต่างกันอยู่ นั่นทำให้ App บน macOS ไม่สามารถรันบน Windows ได้นั่นเอง ทำให้ ถ้าเราจะต้องเขียน Compiler ให้กับทุก OS และสถาปัตยกรรม CPU บนโลก มันน่าจะเป็นเรื่องที่โคตรหัวจะปวดแน่นอน หรือกระทั่ง คนเขียนโปรแกรมเอง ถ้าต้อง Compile ออกมาเป็น Executable ให้กับทุก OS อีก ก็น่าจะเป็นเรื่องปวดหัวมาก ๆ โดยเฉพาะยุคก่อนที่ CPU เรามีหลายแบบ หลายยี่ห้อมาก ๆ
ดีหน่อยว่า ในปัจจุบัน เรามี Executable ที่สามารถยัด Executable Code ของหลาย ๆ สถาปัตยกรรม CPU เข้าไปได้ เช่น Universal Binary ของฝั่ง Apple ที่แพคทั้งชุดคำสั่งสำหรับ CPU Intel และ ARM ของฝั่ง Apple Silicon
Interpretator
ด้วยความยุ่งยากขนาดนี้ ทำให้นักคอมพิวเตอร์เริ่มมองหาตัวเลือกอื่น ๆ เพื่อแก้ไขปัญหา งั้นแทนที่เราจะสร้าง Compiler สำหรับแต่ละเครื่อง ที่ Compile ออกมาเป็น Machine Code งั้นเราลองมาสร้างภาษากลางสักตัว เพื่อให้เรา Compile ครั้งเดียวแล้วเอาไปรันที่ไหนก็ได้ดีกว่ามั้ย นี่แหละ คือไอเดียของ Interpretator
สิ่งที่มันทำคือ มันจะมี Compiler ตัวนึง แต่ความแตกต่างคือ มันจะแปลงออกมาเป็นภาษากลางที่เราเรียกว่า Byte Code แต่แน่นอนว่าเครื่องมันไม่เข้าใจแน่นอน ทำให้เราจะต้องมีโปรแกรมอีกตัวที่ทำหน้าที่เป็นล่ามในการแปลภาษาให้กลายเป็น Machine Code ไปสั่งเครื่องตรง ๆ อีกที เราเรียกโปรแกรมนี้ว่า Interpretator
ความชิบหายมันอยู่ที่ว่า แทนที่มันจะเอาล่ามมาแปลภาษาไว้ก่อน มันเลือกที่จะอ่านไปแปลไป ทำให้ขั้นตอนของมันคือ การอ่านคำสั่งขึ้นมา โยนให้วุ้นแปลภาษา แล้วไปรัน แล้วค่อนกลับไปดึงคำสั่งใหม่ขึ้นมาเป็นแบบนี้ไปเรื่อย ๆ นั่นทำให้มันเกิด Overhead ในการรันสูงมาก ๆ ดังนั้น โดยทั่ว ๆ ไป ภาษาที่ใช้งาน Interpretator ส่วนใหญ่จะรันได้ช้ากว่าภาษาที่เรา Compile ตรง ๆ ไปอยู่มากพอสมควร
Compiler Optimisation
นอกจากลักษณะการทำงานของภาษาต่าง ๆ แล้ว หากเทียบกันในภาษาประเภทเดียวกัน เช่น ภาษาที่ใช้ Compiler เหมือนกัน มันยังทำให้ประสิทธิภาพในการทำงานต่างกันได้อีก เช่น บางภาษาเขามี Compiler ที่โหดมาก ๆ ช่วย Optimise Machine Code ได้เก่งมาก ๆ ถึงแม้ว่าโปรแกรมที่เขียนมาจะแย่ แต่ Optimiser มันเก่งมาก ก็ทำให้ Code ของเรารันได้มีประสิทธิภาพสูงกว่าเดิมได้ หรือกระทั่ง Compiler ออกแบบมาสำหรับ CPU นั้นจริง ๆ มันมักจะมี ชุดคำสั่งพิเศษบางอย่างที่ลัดงานบางอย่างออกไปได้ มันก็อาจจะแปลงไปใช้ ชุดคำสั่งพวกนั้นได้ เช่น มันเห็นว่า คำสั่งทั้งหมดนี้รันบน SIMD ได้ และ CPU รองรับ มันก็อาจจะแปลงให้เป็นเบื้องหลังไปเลย ทำให้ประสิทธิภาพเราทำได้เร็วกว่าเดิมเยอะมาก
Typing
อีกอย่างคือ ถ้าใครเขียนโปรแกรมมาหลาย ๆ ภาษาหน่อย น่าจะพอรู้ว่า มันจะมีทั้งภาษาที่ใช้ Dynamic และ Static Typing อาจจะมองแค่ว่า มันเป็นแค่ลักษณะของไวยกรณ์ของภาษานั้นเฉย ๆ แต่จริง ๆ แล้วมันมีผลกับ Performance อยู่มากพอสมควรเลย
เพราะถ้าเป็น Static Typing ณ เวลารัน มันจะรู้ทันทีว่า มันจะต้องอ่าน Memory ขึ้นมาขนาดเท่าไหร่ จาก Type ที่เรากำหนดไว้ก่อนหน้าแล้ว แต่ถ้าเป็น Dynamic Typing มันจะต้องเข้าไปนั่งหาในตารางอีกว่า มันเป็นตัวไหน Type ไหน ต้องอ่านขึ้นมาเท่าไหร่ คือยุ่งยากกว่ากันเยอะ
ยังไม่นับว่า บางภาษานางฉลาดกว่านั้นมาก อย่าง Python ใส่กลไกสำหรับการจัดการ Memory อย่าง Garbage Collector ที่จะเข้ามา Deallocate หรือคืน Memory ในส่วนที่ไม่ได้ใช้งานแล้วออกไป ทำให้มันจะต้องมีช่วงเวลาที่ Memory จะโดนเก็บกวาด แตกต่างจาก C ที่คนเขียนเองนี่แหละ ที่ต้องทำหน้าที่จัดการเองทั้งหมด หากลืมให้คืน ก็แน่นอนว่า พี่จ๋าแตก Memory Leak กันรัว ๆ อย่างแน่นอน
สรุป
สรุปแล้ว หลัก ๆ ที่จะทำให้ความเร็วแตกต่างกันคือ ลักษณะของภาษาว่า เป็น Compile หรือ Interpretator, Compiler Optimisation และเรื่องอื่น ๆ อย่างการจัดการ Memory ดังนั้น ภาษาแต่ละภาษา เราว่า มันมีข้อดีข้อเสียที่แตกต่างกัน การที่เราใช้ Interpretator ไม่ได้แปลว่า เราจะไม่ใช้มันเพราะมันรันได้ช้า แต่มันทำให้เรา Distribute Software เราได้ง่ายขึ้น และ Learning Curve ต่ำลง เรียนรู้ได้ง่ายขึ้น สุดท้าย มันอยู่ที่ เรา ที่เป็น Programmer ว่า เราควรจะเลือกเครื่องมือ หรือภาษาอะไรในการ Implement ให้มีประสิทธิภาพ ตรงกับการใช้งานมากที่สุดนั่นเอง



