وہ PHP RFC جس نے ایک نیٹیو (native) Polling API کی تعریف کی ہے، اسے منظور کر کے زبان کی ماسٹر برانچ میں شامل کر دیا گیا ہے، جس سے ڈویلپرز کو فائل ڈسکرپٹرز (file descriptors) کو پول کرنے کا ایک تیز رفتار، OS-level طریقہ مل گیا ہے۔ حال ہی میں شامل کیے گئے Fibers کے ساتھ مل کر، PHP کے پاس اب غیر ہم آہنگ (asynchronous) کوڈ کے لیے ایک بلٹ ان اور موثر بنیاد موجود ہے—ایک ایسا خلا جسے پُر کرنے کے لیے طویل عرصے سے لائبریریوں کو اپنے خود کے متبادل طریقے (work-arounds) تیار کرنے پڑ رہے تھے۔
Fibers اور event loop، الگ الگ
Fibers ایک لو-لیول کنٹرول فلو پرائمٹیو (low-level control-flow primitive) ہیں۔ یہ کسی فنکشن کو ایک منتخب مقام پر اپنی ایگزیکیوشن روکنے اور بعد میں بالکل وہیں سے دوبارہ شروع کرنے کی اجازت دیتے ہیں جہاں سے وہ رکا تھا۔ اہم بات یہ ہے کہ ایک fiber کو sockets، timers یا کسی دوسرے I/O سورس کے بارے میں کچھ معلوم نہیں ہوتا؛ یہ صرف ضرورت پڑنے پر رکتا اور دوبارہ شروع ہوتا ہے۔
Event loop وہ شیڈیولر ہے جو فیصلہ کرتا ہے کہ رکے ہوئے fiber کو کب دوبارہ شروع کیا جانا چاہیے۔ ایک عام async stack میں، لوپ فائل ڈسکرپٹرز کے ایک سیٹ پر نظر رکھتا ہے، ان کے قابلِ مطالعہ (readable) یا قابلِ تحریر (writable) ہونے کا انتظار کرتا ہے، اور پھر متعلقہ fiber کو جگاتا ہے۔
PHP میں پہلے سے Fibers موجود تھے لیکن اس میں آپریٹنگ سسٹم سے یہ پوچھنے کا کوئی نیٹیو طریقہ موجود نہیں تھا کہ کون سے ڈسکرپٹرز تیار ہیں۔ اس کا نتیجہ stream_select() یا بیرونی ایکسٹینشنز پر انحصار کی صورت میں نکلا، اور ہر async لائبریری کو Linux کے epoll، BSD کے kqueue، Windows کے IOCP وغیرہ کے لیے اپنے الگ بیک اینڈز لکھنے پڑے۔
نئی Polling API اس کمی کو پورا کرتی ہے۔ یہ OS کی پولنگ سہولیات (Linux پر epoll، BSD/macOS پر kqueue وغیرہ) کے گرد ایک پتلی سی لپیٹ (thin wrapper) فراہم کرتی ہے۔ یہ API Fibers کی جگہ نہیں لیتی؛ یہ صرف event loop کو وہ رفتار اور پیمانہ کاری (scalability) فراہم کرتی ہے جس کی اسے ضرورت ہے۔
ReactPHP، Amp اور دیگر کے لیے یہ تبدیلی کیوں اہم ہے
ReactPHP اور Amp v3 نے OS پولنگ میکانزم کے اوپر اپنے ایبسٹریکشن لیئرز (abstraction layers) بنائے ہیں۔ ان لیئرز میں کوڈ کے متعدد راستے شامل ہیں، جن میں سے ہر ایک کو ایک مخصوص پلیٹ فارم کے لیے تیار کیا گیا ہے، اور انہیں کرنل کی تبدیلیوں کے ساتھ ہم آہنگ رکھنا ضروری ہوتا ہے۔ ایک نیٹیو Polling API کے ساتھ، لائبریریاں اس زیادہ تر پیچیدہ کام (plumbing) کو ختم کر سکتی ہیں اور ایک واحد، کور (core) کے ذریعے فراہم کردہ کال پر انحصار کر سکتی ہیں۔
- Maintenance – پلیٹ فارم کے لحاظ سے مخصوص شاخوں (branches) کا کم ہونا مطلب کم بگ (bugs) اور سیکیورٹی ریویوز کے لیے کم تر سطح۔
- Performance – نیٹیو کال براہ راست epoll/kqueue سے بات کرتی ہے۔
- Portability – "vanilla" PHP پر چلنے والا کوڈ اب تمام معاون آپریٹنگ سسٹمز پر ایک جیسی بنیادی کارکردگی حاصل کرے گا، بغیر کسی اختیاری ایکسٹینشن کی ضرورت کے۔
اس کے برعکس، Swoole ایک مکمل رن ٹائم متبادل ہے جو اپنا event loop اور coroutine سسٹم فراہم کرتا ہے۔ Polling API Swoole کے انتخاب پر اثر انداز نہیں ہوتی؛ وہ ڈویلپرز جنہیں انتہائی کم لیٹنسی (ultra-low latency) یا کسٹم میموری مینجمنٹ کی ضرورت ہے، وہ اب بھی اسے ایک الگ آپشن کے طور پر ہی دیکھیں گے۔
ایک فوری بینچ مارک صورتحال واضح کرتا ہے
ایک کم سے کم (minimal) شیڈیولر نے متعدد fibers کو مینیج کرنے کے لیے ایک واحد Io\Poll\Context کا استعمال کرتے ہوئے، را (raw) sockets کے ذریعے کئی URLs حاصل کیے۔ دو مشاہدات سامنے آئے:
- Speed – مزید بیک وقت (concurrent) درخواستیں شامل کرنے سے کل گزرے ہوئے وقت میں اضافہ نہیں ہوتا؛ درخواستوں کا بیچ (batch) اتنی ہی جلدی مکمل ہو جاتا ہے جتنی جلدی سب سے سست انفرادی درخواست۔ دوسرے لفظوں میں، کنکرنسی کا اوور ہیڈ (concurrency overhead) مؤثر طور پر صفر ہے۔
- CPU cost –
stream_select()کے ساتھ، جیسے جیسے اسٹریمز کی تعداد بڑھتی ہے، CPU کا استعمال نمایاں طور پر بڑھ جاتا ہے، کیونکہ فنکشن کو ہر کال پر ہر ڈسکرپٹر پر بار بار جانا پڑتا ہے۔ Polling API کی لاگت تین اسٹریمز سے لے کر تیس اسٹریمز تک مستحکم رہتی ہے، کیونکہ کرنل میں ایک ہی سسٹم کال میں بہت سے ڈسکرپٹرز کی نگرانی کرنے کی صلاحیت موجود ہے۔
ڈویلپرز کو اب کیا کرنا چاہیے
- Amp v3 کو اپنائیں اگر آپ fiber-native انداز کو ترجیح دیتے ہیں جو براہ راست نئی API کے مطابق ہے۔ اس کا پبلک انٹرفیس پہلے ہی بنیادی پولر (poller) کے ساتھ منسلک ہے، اس لیے آپ کو اپنا کوڈ دوبارہ لکھے بغیر اس کا فائدہ ملے گا۔
- ReactPHP کے ساتھ رہیں اگر آپ لوپ کی لائف سائیکل پر واضح کنٹرول پسند کرتے ہیں۔
- پروڈکشن ورک لوڈز کے لیے کسٹم شیڈیولرز سے پرہیز کریں۔ پروڈکشن کے لیے اپنا شیڈیولر خود نہ لکھیں۔
