สิ่งที่ผมได้เรียนรู้ในฐานะนักพัฒนา PHP แบบ Sync เกี่ยวกับ Async PHP

ผมทำงานกับ Laravel มาหลายปี ผมใช้ PHP แบบ sync เมื่อมี request เข้ามา กระบวนการจะทำงาน และส่ง response ออกไป ผมไม่เคยคิดว่าต้องใช้ async เลย

จนกระทั่งผมได้อ่านเรื่อง PHP 8.6 Polling API ตัวใหม่ มันเปลี่ยนมุมมองของผมที่มีต่อวิธีที่ PHP จัดการกับงานต่างๆ

นี่คือรายละเอียดว่า async ทำงานอย่างไร

ปัญหาของ Blocking I/O

เมื่อคุณเรียกใช้ API โค้ดของคุณจะหยุดรอ ตัวอย่าง: $response = Http::get('https://api.example.com');

หาก API นั้นใช้เวลา 300ms กระบวนการ PHP ของคุณจะไม่ได้ทำอะไรเลยเป็นเวลา 300ms มันจะอยู่ในสถานะ sleep ซึ่งกินหน่วยความจำและจองช่องว่างของ worker ไว้ หาก worker ทั้งหมดของคุณกำลัง sleep อยู่ เซิร์ฟเวอร์ของคุณก็จะหยุดรับ request ใหม่ๆ

ทางออกด้วย Async

Async ช่วยให้คุณสามารถทำงานอื่นได้ในระหว่าง 300ms นั้น แทนที่จะรอเฉยๆ คุณสามารถรันงานอื่นๆ ต่อไปได้

แต่คุณจะรู้ได้อย่างไรว่าข้อมูลมาถึงแล้ว? นี่คือจุดที่ kernel เข้ามามีบทบาท

วิวัฒนาการของ Polling

  1. select() PHP มี stream_select() มาตั้งแต่ PHP 4 โดยมันจะถาม kernel ว่า: "มีข้อมูลพร้อมใน socket เหล่านี้บ้างไหม?" ปัญหาคือภาระในการสแกนซ้ำ (rescan tax) หากคุณมีการเชื่อมต่อ 10,000 รายการ คุณต้องส่งรายการทั้งหมดไปให้ kernel ทุกครั้ง ซึ่งมันช้าและถึงขีดจำกัดได้ง่าย

  2. epoll / kqueue นี่คือฟีเจอร์ของ kernel ไม่ใช่ฟีเจอร์ของภาษา Linux ใช้ epoll ส่วน macOS ใช้ kqueue แทนที่จะสแกนรายการทั้งหมด kernel จะรักษา "ready-list" ไว้ และจะบอกคุณเฉพาะ socket ที่มีข้อมูลเท่านั้น วิธีนี้สามารถรองรับการเชื่อมต่อได้เป็นพันๆ โดยไม่มีต้นทุนที่เพิ่มขึ้น

  3. Fibers (PHP 8.1) Fibers ช่วยให้คุณสามารถหยุดการทำงานของฟังก์ชัน (pause) ตรงไหนก็ได้ใน call stack Fiber ไม่สามารถตื่นขึ้นมาเองได้ มันเหมือนกับวิดีโอ YouTube ที่ถูกกดหยุดไว้ ต้องมีใครบางคนเรียก $fiber->resume() เพื่อให้มันเล่นต่อ

จิ๊กซอว์ชิ้นที่หายไป: PHP 8.6

Async I/O ต้องใช้ 3 ส่วนประกอบ: • Pause: Fibers (ตอนนี้อยู่ใน PHP core แล้ว) • Decide: The Event Loop (โค้ด PHP ปกติ) • Know: Kernel Polling (ช่องว่างที่หายไป)

จนถึงตอนนี้ PHP ยังขาดวิธีแบบ native ในการ "รู้" ว่า socket ไหนพร้อมใช้งาน โดยไม่ต้องใช้เครื่องมือเก่าๆ หรือ C extensions

PHP 8.6 จะมาปิดช่องว่างนี้ โดยการนำ Polling API แบบ native เข้ามาไว้ใน core ซึ่งมันจะใช้ epoll บน Linux และ kqueue บน Mac โดยอัตโนมัติ

ภาพรวม

Async ไม่ใช่เวทมนตร์ Event loop เป็นเพียงโค้ด PHP ที่ตัดสินใจว่าจะเรียก resume() บน Fiber เมื่อไหร่

Fibers มอบความสามารถในการหยุด (pause) epoll มอบความฉลาดในการรู้ว่าเมื่อไหร่ควรจะหยุดพัก (unpause)

หากคุณใช้เพียงแค่ sync PHP คุณยังไม่จำเป็นต้องเปลี่ยนแอป Laravel ของคุณในวันนี้ แต่การเข้าใจโมเดลนี้จะทำให้การใช้งาน library แบบ async อย่าง ReactPHP หรือ Amp ง่ายขึ้นมาก

จงสร้าง อย่าเพียงแค่บริโภค ลองรันโค้ดด้วยตัวเองเพื่อดูว่ามันทำงานอย่างไร

Source: https://dev.to/alamriku/sync-php-developer-hisebe-async-php-bujhte-giye-yaa-shikhlaam-fibers-epoll-aar-php-86-462j