PyPy: เร็วขึ้น 5 เท่า แต่บางทีก็เจอรักขม

สวัสดีครับทุกคน! วันนี้มาคุยเรื่อง Python ที่หลายคนอาจจะเคยได้ยินแต่ไม่เคยลองใช้จริงจัง นั่นก็คือ PyPy นั่นเอง

PyPy คืออะไร ทำไมต้องสน?

PyPy มันคือ Python Interpreter อีกตัวนะ ไม่ใช่แค่รันไทม์ปกติที่มาจาก CPython ที่เราใช้กันประจำๆ แต่มันมีของดีคือ JIT Compiler (Just-In-Time Compiler) ทำให้โค้ดของเรามันรันได้เร็วจี๋เลย บางเคสคือเห็นผลชัดเจนมาก 3-5 เท่าก็มีให้เห็นเยอะแยะเลยแหละ

ลองคิดดูดิ ถ้าโปรเจกต์คุณมัน CPU-bound แล้วโค้ดไม่ได้ไปเรียกอะไรแปลกๆ เยอะ การเปลี่ยนมารันกับ PyPy มันเหมือนได้อัปเกรดเครื่องฟรีๆ เลยนะ โคตรคุ้ม!

เริ่มใช้ PyPy ยังไงดี?

การลง PyPy มันไม่เหมือนลงไลบรารีปกติใน Python นะ มันคือ Interpreter เลย เวลาใช้ก็ต้องดาวน์โหลดมาติดตั้งแยกต่างหาก อย่างผมชอบใช้ pyenv ก็จะประมาณนี้

pyenv install pypy3.10-7.3.13  # เลือกเวอร์ชั่นที่ต้องการ
pyenv global pypy3.10-7.3.13 # ถ้าอยากให้เป็น default เลย (ระวัง!)

หรือถ้าอยากลองใช้แค่ในโปรเจกต์นั้นๆ ก็ใช้ pyenv local เอา

ลองเช็คดู python --version หรือ pypy --version ถ้าเจอ PyPy ก็คือใช้ได้แล้ว

มาลองดูกันว่ามันเร็วจริงไหม?

ลองเขียนโค้ดง่ายๆ มาเปรียบเทียบความเร็วกันดีกว่า

# test_speed.py
import time

def factorial(n):
    if n == 0:
        return 1
    return n * factorial(n - 1)

start_time = time.time()
for _ in range(10000): # ลองวนซักหมื่นรอบ
    factorial(50)
end_time = time.time()

print(f"ใช้เวลาไป: {end_time - start_time:.4f} วินาที")

แล้วลองรันด้วย CPython ปกติ

python test_speed.py
# ตัวอย่างผลลัพธ์: ใช้เวลาไป: 0.2875 วินาที

ทีนี้มารันด้วย PyPy (ถ้าคุณตั้งค่า pyenv หรือ path ไว้ดีแล้ว)

pypy test_speed.py
# ตัวอย่างผลลัพธ์: ใช้เวลาไป: 0.0521 วินาที

คุณจะเห็นเลยว่า PyPy มันเร็วกว่าเยอะมากกกกกก! สำหรับโค้ดแบบนี้ที่ไม่มี I/O เยอะๆ หรือเรียก C extension ที่ซับซ้อน มันคือเทพเลยครับ

The "รักขม" ของ PyPy

แต่ชีวิตมันไม่ได้ง่ายขนาดนั้นไง! PyPy มันมีจุดอ่อนที่โคตรน่าหงุดหงิดเลย นั่นก็คือเรื่องของ C Extensions

คือเวลาที่เราใช้ไลบรารีที่เขียนด้วย C/C++ แล้วมีส่วนที่คอมไพล์มาเป็น .so หรือ .dll ไฟล์เนี่ย บางที PyPy มันไม่เข้าใจ หรือไม่สามารถ JIT คอมไพล์ส่วนนั้นได้ดีเท่า CPython

ยกตัวอย่างง่ายๆ เลย พวก numpy, pandas, หรือแม้กระทั่ง cryptography บางเวอร์ชั่น ถ้าไปใช้กับ PyPy ตรงๆ อาจจะเจอปัญหาได้เลยนะ

ตัวอย่าง Error ที่เคยเจอ:

เคยเจอมั้ยล่ะ เวลาจะลง cryptography ใน PyPy แล้วมันฟ้องแบบนี้...

Collecting cryptography
  Downloading cryptography-3.4.8.tar.gz (547 kB)
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 547.7/547.7 kB 4.3 MB/s eta 0:00:00
  Installing build dependencies ... error
  error: subprocess-exited-with-error

  × pip subprocess to install build dependencies did not run successfully.
  │ exit code: 1
  ╰─> [24 lines of output]
      # ... (truncated for brevity) ...
      # บางทีมันจะฟ้องเกี่ยวกับ `rust` หรือ `cffi` หรือ `setuptools_rust` อะไรทำนองนี้
      # คือมันพยายามจะคอมไพล์ C extension แต่ PyPy มันงอแงไม่ยอมให้ผ่าน
      # หรือบางทีก็เป็นเรื่องของ ABI (Application Binary Interface) mismatch
      # ทำให้ใช้ไลบรารีที่ pre-compiled มากับ CPython ไม่ได้
      Could not build wheels for cryptography, which is required to install pyproject.toml-based projects
      [end of output]
  note: This error originates from a subprocess, and is not an issue with pip.
error: subprocess-exited-with-error

× pip subprocess to install build dependencies did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is not an issue with pip.

เจอแบบนี้ก็ปวดหัวดิ! บางทีเราก็อยากได้ความเร็ว แต่ก็ต้องแลกกับความเข้ากันได้ของไลบรารีที่เราใช้ คือบางโปรเจกต์มันใช้ numpy หรือ pandas เป็นหลักอะ จะไปใช้ PyPy ก็ต้องคิดหนักมากๆ เลยนะ หรือไม่ก็ต้องหาไลบรารีอื่นที่ไม่มี C extension มาแทน ซึ่งบางทีมันก็เป็นไปไม่ได้ไง

ดังนั้น เวลาจะใช้ PyPy ให้คิดดีๆ ก่อนว่าโปรเจกต์เรามี dependency อะไรที่ต้องพึ่ง C extension เยอะมั้ย ถ้าไม่เยอะ หรือเป็นโค้ด Python เพียวๆ เลย อันนี้ PyPy คือพระเอกแน่นอน แต่ถ้ามีพวกนี้เยอะๆ ก็ต้องทำใจ หรือไม่ก็ลองหาเวอร์ชั่นของไลบรารีที่ PyPy มันรองรับดีๆ (ซึ่งอาจจะต้องใช้เวอร์ชั่นเก่ามากๆ) บอกเลยว่าชีวิตนักพัฒนาไม่เคยง่าย!

สรุป

สรุปคือ PyPy มันเป็นของดีจริงๆ ในแง่ของ performance แต่ก็มีข้อจำกัดเรื่อง C extensions ที่ต้องระวัง ถ้าโปรเจกต์คุณเหมาะกับมัน คือไม่ได้ใช้ไลบรารีพวกนั้นเยอะ ลองใช้ดูครับ คุณจะทึ่งในความเร็วของมัน แต่ถ้าไม่... ก็กลับมาใช้ CPython เหมือนเดิมก็ได้ ไม่ได้เสียหายอะไร! เลือกใช้ให้ถูกกับงานนะครับ

หวังว่าบทความนี้จะเป็นประโยชน์สำหรับคนที่อยากลองอะไรใหม่ๆ กับ Python นะครับ เจอกันบทความหน้า!

Read more

PSG vs Monaco: ศึก 100 นัดเดือด ลีกเอิง และบทเรียนที่ปาร์ค เดส์ แพร็งซ์

PSG vs Monaco: ศึก 100 นัดเดือด ลีกเอิง และบทเรียนที่ปาร์ค เดส์ แพร็งซ์

สรุปผลและวิเคราะห์เกมเดือด PSG พบ Monaco ในลีกเอิงนัดที่ 25 ซึ่งเป็นการพบกันครั้งที่ 100 ในประวัติศาสตร์ลีก ความพ่ายแพ้ 1-3 คาบ้านของ PSG และบทบาทของ Akliouche พร้อมผลกระทบต่อเส้นทางแชมเปี้ยนส์ลีก

By ทีมงาน devdog
บาเยิร์นผงาดไร้เคน! ถล่มกลัดบัค 4-1 โชว์ความลึกของทีมก่อนลุยศึก UCL

บาเยิร์นผงาดไร้เคน! ถล่มกลัดบัค 4-1 โชว์ความลึกของทีมก่อนลุยศึก UCL

บาเยิร์น มิวนิค โชว์ฟอร์มแกร่ง แม้ไม่มีแฮร์รี่ เคน ถล่ม โบรุสเซีย มึนเชนกลัดบัค 4-1 ก่อนเตรียมลุยศึกแชมเปียนส์ลีกกับอตาลันต้า!

By ทีมงาน devdog
PSG: มหาอำนาจลูกหนังฝรั่งเศส กับศึกดวลเดือดโมนาโก และเป้าหมายสู่บัลลังก์ยุโรป

PSG: มหาอำนาจลูกหนังฝรั่งเศส กับศึกดวลเดือดโมนาโก และเป้าหมายสู่บัลลังก์ยุโรป

เจาะลึกเส้นทาง PSG สู่มหาอำนาจลูกหนัง วิเคราะห์สถานการณ์ลีกเอิง เตรียมพร้อมศึกใหญ่กับโมนาโก พร้อมความมุ่งมั่นสู่แชมป์ยุโรป

By ทีมงาน devdog
ลาลีกา: มนต์เสน่ห์ฟุตบอลสเปน, นวัตกรรมเรโทร, และบิ๊กแมตช์แห่งอนาคต

ลาลีกา: มนต์เสน่ห์ฟุตบอลสเปน, นวัตกรรมเรโทร, และบิ๊กแมตช์แห่งอนาคต

สำรวจลาลีกา ฟุตบอลสเปนอันทรงเสน่ห์ พร้อมไฮไลต์บิ๊กแมตช์ 2025/26 นวัตกรรมสัปดาห์เรโทร และบทบาทต่อวัฒนธรรมและเศรษฐกิจ.

By ทีมงาน devdog