PyPy: Python เร็วขึ้นแบบเห็นๆ (แต่บางทีก็มีงอแง)
โค้ด Python ที่เราเขียนๆ กันอยู่เนี่ย มันรันบน CPython ซึ่งเป็น Interpreter ตัวหลักที่ใช้กันทั่วไปนั่นแหละ แล้วถามว่ามันเร็วไหม? อืมม... ก็ไม่ได้ช้าขนาดนั้นนะ แต่ก็ไม่ได้เร็วแบบจรวด บางทีเจอ Loop หนักๆ หรือคำนวณเยอะๆ เนี่ยก็แอบหงุดหงิดเหมือนกัน
ทีนี้มันมีของดีอีกตัว ชื่อ PyPy
PyPy คืออะไร?
PyPy เนี่ย จริงๆ มันก็คือ Python Interpreter อีกตัวนี่แหละ แต่ความพิเศษของมันคือมันใช้เทคนิคที่เรียกว่า JIT (Just-In-Time) Compilation คือแทนที่จะแปลโค้ดทีละบรรทัดแบบ CPython มันจะพยายามวิเคราะห์โค้ดเราตอนรัน แล้วคอมไพล์ส่วนที่ใช้บ่อยๆ ให้เป็น Machine Code เลย ทำให้มันรันได้เร็วขึ้นเยอะมาก เวลาเจอ Loop วนซ้ำๆ เยอะๆ เนี่ย PyPy จะโชว์พลังได้ดีสุดๆ
ลองใช้ PyPy กัน!
มาลองดูวิธีติดตั้ง PyPy ง่ายๆ กันนะ หลักๆ ผมแนะนำใช้ pyenv นะ มันจัดการเวอร์ชั่น Python ได้โคตรดีเลย
# ติดตั้ง pyenv ถ้ายังไม่มี
curl https://pyenv.run | bash
# ติดตั้ง PyPy ล่าสุด (ลองเช็คเวอร์ชั่นล่าสุดในเว็บ PyPy.org ก่อนก็ดี)
pyenv install pypy3.9-7.3.11 # ตัวเลขเวอร์ชั่นอาจจะเปลี่ยนไปนะ ลองเช็คดู
# ตั้งค่าให้ใช้ PyPy สำหรับโปรเจกต์ปัจจุบัน
pyenv local pypy3.9-7.3.11
# หรือจะตั้งค่าเป็น global ก็ได้ถ้าจะใช้ทั่วเครื่อง
pyenv global pypy3.9-7.3.11
# เช็คว่าใช้ PyPy รึยัง
python --version
# ควรจะเห็นอะไรประมาณนี้: PyPy 3.9.18 (7.3.11, Jun 26 2023, 19:42:07)
# [PyPy 7.3.11 with GCC 11.3.0]
พอติดตั้งเสร็จ ลองเขียนโค้ดง่ายๆ มาเทียบความเร็วดู (ไฟล์ speed_test.py):
# speed_test.py
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a
import time
start_time = time.time()
result = fibonacci(1000000) # ลองคำนวณเลขเยอะๆ
end_time = time.time()
print(f"Fibonacci result: {result % 1000000000}") # เอาแค่ไม่กี่หลักท้ายๆ พอ
print(f"Time taken: {end_time - start_time:.4f} seconds")
ลองรันด้วย CPython ก่อน (ถ้าเครื่องคุณมี CPython เป็น default หรือใช้ pyenv global system)
python speed_test.py
# ตัวอย่างผลลัพธ์: Time taken: 0.1500 seconds (อันนี้ขึ้นกับเครื่องนะ)
แล้วมาลองรันด้วย PyPy
pypy speed_test.py
# หรือถ้าใช้ pyenv ก็แค่
python speed_test.py
# ตัวอย่างผลลัพธ์: Time taken: 0.0120 seconds (เห็นป่ะ โคตรเร็ว!)
จะเห็นว่า PyPy ทำงานเร็วกว่า CPython อย่างเห็นได้ชัดสำหรับงานที่ต้องคำนวณหนักๆ หรือมี Loop เยอะๆ แบบนี้ มันปังมากกกก!
ข้อควรระวัง (มีงอแงบ้าง):
ถึง PyPy จะเร็วเวอร์ แต่ก็ไม่ได้เหมาะกับทุกงานนะ
- Startup Time: สำหรับสคริปต์สั้นๆ ที่รันแป๊บเดียว PyPy อาจจะไม่ได้เร็วกว่า CPython นะ เพราะมันมี Overhead ในการ 'Warm Up' JIT Compiler นี่แหละ
- Memory Usage: บางเคส PyPy อาจจะกิน RAM เยอะกว่า CPython บ้าง เพราะต้องมีส่วนของ JIT Compiler และข้อมูลการวิเคราะห์โค้ดเพิ่มเติม
ไม่ถูกกับ C Extensions: นี่คือปัญหาใหญ่เลย ถ้าโปรเจกต์คุณใช้ไลบรารีที่เขียนด้วย C เป็นหลัก เช่น NumPy, SciPy, Pandas (บางส่วน) อะไรพวกนี้เนี่ย PyPy อาจจะงอแงได้ เพราะมันต้องใช้ CFFI (C Foreign Function Interface) แทน ซึ่งบางทีก็ไม่เสถียรเท่า หรือบางแพ็กเกจก็ยังไม่รองรับดีนักตัวอย่าง Error ที่เคยเจอ:
$ pip install numpy
Collecting numpy
Using cached numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (18.2 MB)
Installing collected packages: numpy
Successfully installed numpy-1.26.4
# ดูเหมือนจะติดตั้งได้นะ แต่พอรันจริงอาจมีปัญหา
>>> import numpy
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: This numpy binary was compiled for CPython.
PyPy is not compatible with it. You might need to rebuild it for PyPy.
Or install from source if possible.
คือมันบอกชัดเลยว่าไบนารี numpy ที่โหลดมามันคอมไพล์มาเพื่อ CPython เท่านั้นน่ะดิ! วิธีแก้ก็คือต้องหา numpy เวอร์ชั่นที่รองรับ PyPy หรือคอมไพล์จาก source เอง ซึ่งบอกเลยว่าไม่ง่าย หรือบางทีก็ทำไม่ได้เลยจ้าาา เศร้าเลยตรงนี้
สรุปความเห็นส่วนตัว
ผมว่า PyPy มันเป็นตัวเลือกที่น่าสนใจมากๆ สำหรับงานที่เน้นประสิทธิภาพการประมวลผล Python ดิบๆ อย่างพวก Algorithm, Data Processing ที่ไม่ได้พึ่งพาไลบรารี C/C++ มากมาย ถ้าคุณเขียน Machine Learning หรือ Data Science แบบใช้ NumPy, Pandas เป็นหลักเนี่ย ไป CPython ดีกว่า หรือถ้าอยากเร็วก็หาวิธี optimize ตรงนั้นไป PyPy ไม่ใช่ทางออก
แต่ถ้าโค้ดคุณส่วนใหญ่เป็น Python ล้วนๆ แล้วมันช้าเหลือเกิน ลองโยนไปรันด้วย PyPy ดูดิ อาจจะเห็นความต่างแบบตะลึง! มันเหมือนเป็นทางลัดสู่ความเร็วที่บางทีก็เวิร์ค บางทีก็ไม่เวิร์คนะ ต้องลองเองถึงจะรู้!