האמת על Async PHP: Fibers, epoll ו-PHP 8.6

עבדתי עם Laravel במשך שנים. השתמשתי ב-sync PHP. בקשה מגיעה, התהליך רץ, והתגובה נשלחת. מעולם לא נזקקתי לקוד async.

ואז קראתי על ה-Polling API החדש של PHP 8.6. זה שינה את הדרך שבה אני רואה הכל.

הנה מה שלמדתי על האופן שבו async עובד מתחת למכסה המנוע.

בעיית ה-IO

כשאתה קורא ל-API, תהליך ה-PHP שלך ממתין. דוגמה: $response = Http::get('https://api.example.com');

אם הקריאה הזו לוקחת 300ms, ה-CPU שלך לא עושה כלום במשך 300ms. הוא נשאר במצב שינה (sleep state). זהו blocking I/O.

אם יש לך שלוש קריאות API:

  • API A: 300ms
  • API B: 400ms
  • API C: 200ms

סה"כ סדרתי (Sequential): 900ms. סה"כ async: 400ms (הזמן של הקריאה האיטית ביותר).

Async מאפשר לתהליך שלך לבצע עבודה אחרת בזמן ההמתנה לנתונים.

Select לעומת epoll

כדי לבצע async, אתה צריך לדעת לאיזה socket יש נתונים מוכנים.

  1. select() PHP משתמשת ב-stream_select() מגרסה 4. זה עובד על ידי בקשה מה-kernel לעקוב אחר רשימה של sockets. הבעיה: בכל פעם שנתונים מגיעים, עליך לסרוק את הרשימה כולה מחדש. זוהי עלות של סריקה מחדש (rescan tax). יש לה גם מגבלה של כ-1024 חיבורים.

  2. epoll (Linux) / kqueue (macOS) אלו הן תכונות של ה-kernel. במקום לסרוק רשימה, ה-kernel שומר רשימת מוכנות (ready-list). הוא רק אומר לך אילו sockets ספציפיים מוכנים. זה עושה scale לאלפי חיבורים ללא עבודה נוספת.

epoll אינו תכונה של PHP. זוהי תכונה של Linux. Go, Rust ו-Node.js כולם משתמשים בו.

Fibers: כפתור ההשהיה

PHP 8.1 הציגה את ה-Fibers. חשבתי שה-Fibers יתעוררו מעצמם. הם לא עושים זאת.

Fiber הוא כמו סרטון עצור (paused). הוא נשאר עצור עד שמישהו קורא ל-$fiber->resume().

Event Loop הוא פשוט קטע קוד PHP שמחליט מתי לקרוא ל-resume().

Async I/O דורש שלושה חלקים:

  • Pause (השהיה): Fibers (ליבת PHP 8.1)
  • Decide (החלטה): ה-Event Loop (קוד PHP רגיל)
  • Know (ידיעה): Kernel Polling (epoll/kqueue)

לפני PHP 8.6, ל-PHP היו חלקי ה-"Pause" וה-"Decide", אך חלק ה-"Know" הסתמך על ה-select() הישן או על הרחבות (extensions) איטיות ב-C.

PHP 8.6 סוגרת את הפער הזה. היא מביאה Polling API מובנה (native) לליבה. כעת, PHP יכולה להשתמש ב-epoll או kqueue ישירות ללא הרחבות נוספות.

השורה התחתונה

אם אתה משתמש ב-Laravel עם PHP-FPM, אתה לא צריך לשנות כלום היום.

אבל תבין את זה: Async הוא לא קסם. זוהי רק דרך חכמה לנהל זמן המתנה.

תפסיק רק לצרוך קוד. תריץ סקריפט פשוט. תשבור אותו. ככה באמת לומדים.

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