Python کوڈ کی 4 ملین لائنوں کو ٹائپ چیک کرنے کا راستہ۔ حصہ 2

آج ہم مواد کے ترجمے کا دوسرا حصہ شائع کر رہے ہیں کہ کیسے ڈراپ باکس نے Python کوڈ کی کئی ملین لائنوں کے لیے ٹائپ کنٹرول کو منظم کیا۔

Python کوڈ کی 4 ملین لائنوں کو ٹائپ چیک کرنے کا راستہ۔ حصہ 2

پہلا حصہ پڑھیں

سرکاری قسم کی حمایت (PEP 484)

ہم نے ہیک ویک 2014 کے دوران ڈراپ باکس میں mypy کے ساتھ اپنے پہلے سنجیدہ تجربات کیے تھے۔ ہیک ویک ایک ہفتے کا پروگرام ہے جس کی میزبانی Dropbox کے ذریعے کی جاتی ہے۔ اس وقت کے دوران، ملازمین جو چاہیں کام کر سکتے ہیں! ڈراپ باکس کے سب سے مشہور ٹیکنالوجی پروجیکٹس میں سے کچھ اس طرح کے واقعات سے شروع ہوئے۔ اس تجربے کے نتیجے میں، ہم نے یہ نتیجہ اخذ کیا کہ mypy امید افزا لگ رہا ہے، حالانکہ یہ منصوبہ ابھی تک وسیع پیمانے پر استعمال کے لیے تیار نہیں ہے۔

اس وقت، Python قسم کے اشارے کے نظام کو معیاری بنانے کا خیال ہوا میں تھا۔ جیسا کہ میں نے کہا، ازگر 3.0 کے بعد سے فنکشنز کے لیے قسم کی تشریحات کا استعمال ممکن تھا، لیکن یہ صرف صوابدیدی اظہار تھے، بغیر کسی وضاحتی نحو اور الفاظ کے۔ پروگرام پر عمل درآمد کے دوران، ان تشریحات کو، زیادہ تر حصے کے لیے، محض نظر انداز کر دیا گیا۔ ہیک ویک کے بعد، ہم نے سیمنٹکس کو معیاری بنانے پر کام شروع کیا۔ یہ کام ظہور کا باعث بنا پیئ پی 484 (Guido van Rossum, Łukasz Langa اور میں نے اس دستاویز پر تعاون کیا)۔

ہمارے مقاصد کو دو زاویوں سے دیکھا جا سکتا ہے۔ سب سے پہلے، ہم نے امید ظاہر کی کہ پورا Python ماحولیاتی نظام ٹائپ اشارے استعمال کرنے کے لیے ایک مشترکہ نقطہ نظر اپنا سکتا ہے (ایک اصطلاح جو Python میں "ٹائپ تشریحات" کے مساوی استعمال ہوتی ہے)۔ یہ، ممکنہ خطرات کے پیش نظر، بہت سے باہمی طور پر غیر مطابقت پذیر طریقوں کو استعمال کرنے سے بہتر ہوگا۔ دوسرا، ہم Python کمیونٹی کے بہت سے ممبران کے ساتھ ٹائپ اینوٹیشن میکانزم پر کھل کر بات کرنا چاہتے تھے۔ یہ خواہش جزوی طور پر اس حقیقت کی طرف سے طے کی گئی تھی کہ ہم Python پروگرامرز کے وسیع عوام کی نظر میں زبان کے بنیادی نظریات سے "مرتد" کی طرح نظر نہیں آنا چاہیں گے۔ یہ متحرک طور پر ٹائپ کی جانے والی زبان ہے، جسے "بطخ ٹائپنگ" کہا جاتا ہے۔ کمیونٹی میں، بالکل شروع میں، جامد ٹائپنگ کے خیال کے بارے میں کسی حد تک مشتبہ رویہ مدد نہیں کرسکتا لیکن پیدا ہوتا ہے۔ لیکن یہ جذبہ آخر کار اس وقت ختم ہو گیا جب یہ واضح ہو گیا کہ جامد ٹائپنگ لازمی نہیں ہوگی (اور لوگوں کو یہ احساس ہونے کے بعد کہ یہ واقعی مفید ہے)۔

قسم کے اشارے کا نحو جو بالآخر اپنایا گیا تھا اس سے بہت ملتا جلتا تھا جس کی اس وقت mypy نے حمایت کی تھی۔ PEP 484 Python 3.5 کے ساتھ 2015 میں جاری کیا گیا تھا۔ Python اب متحرک طور پر ٹائپ کی جانے والی زبان نہیں تھی۔ میں اس واقعہ کو ازگر کی تاریخ میں ایک اہم سنگ میل کے طور پر سوچنا چاہتا ہوں۔

ہجرت کا آغاز

2015 کے آخر میں، ڈراپ باکس نے mypy پر کام کرنے کے لیے تین لوگوں کی ایک ٹیم بنائی۔ ان میں گائیڈو وین روسم، گریگ پرائس اور ڈیوڈ فشر شامل تھے۔ اس لمحے سے، صورت حال بہت تیزی سے تیار کرنے کے لئے شروع کر دیا. mypy کی ترقی میں پہلی رکاوٹ کارکردگی تھی۔ جیسا کہ میں نے اوپر اشارہ کیا، پروجیکٹ کے ابتدائی دنوں میں میں نے mypy کے نفاذ کو C میں ترجمہ کرنے کے بارے میں سوچا تھا، لیکن یہ خیال ابھی کے لیے فہرست سے باہر ہو گیا تھا۔ ہم CPython انٹرپریٹر کا استعمال کرتے ہوئے سسٹم کو چلانے میں پھنس گئے تھے، جو mypy جیسے ٹولز کے لیے کافی تیز نہیں ہے۔ (PyPy پروجیکٹ، JIT کمپائلر کے ساتھ ایک متبادل Python نفاذ، نے بھی ہماری مدد نہیں کی۔)

خوش قسمتی سے، یہاں کچھ الگورتھمک بہتری ہماری مدد کے لیے آئی ہے۔ پہلا طاقتور "ایکسیلیٹر" انکریمنٹل چیکنگ کا نفاذ تھا۔ اس بہتری کے پیچھے خیال آسان تھا: اگر ماڈیول کے تمام انحصار mypy کے پچھلے رن کے بعد سے تبدیل نہیں ہوئے ہیں، تو ہم انحصار کے ساتھ کام کرتے ہوئے پچھلے رن کے دوران کیش کردہ ڈیٹا کو استعمال کر سکتے ہیں۔ ہمیں صرف ترمیم شدہ فائلوں اور ان فائلوں پر ٹائپ چیکنگ کرنے کی ضرورت ہے جو ان پر منحصر ہیں۔ Mypy یہاں تک کہ تھوڑا آگے چلا گیا: اگر ماڈیول کا بیرونی انٹرفیس تبدیل نہیں ہوتا ہے تو، mypy نے فرض کیا کہ اس ماڈیول کو درآمد کرنے والے دوسرے ماڈیولز کو دوبارہ چیک کرنے کی ضرورت نہیں ہے۔

موجودہ کوڈ کی بڑی مقدار کی تشریح کرتے وقت اضافی چیکنگ نے ہماری بہت مدد کی ہے۔ نقطہ یہ ہے کہ اس عمل میں عام طور پر mypy کے بہت سے تکراری رنز شامل ہوتے ہیں کیونکہ تشریحات کو آہستہ آہستہ کوڈ میں شامل کیا جاتا ہے اور آہستہ آہستہ بہتر کیا جاتا ہے۔ mypy کا پہلا رن ابھی بھی بہت سست تھا کیونکہ اس میں چیک کرنے کے لئے بہت زیادہ انحصار تھا۔ پھر، صورتحال کو بہتر بنانے کے لیے، ہم نے ریموٹ کیشنگ میکانزم کو نافذ کیا۔ اگر mypy کو پتہ چلتا ہے کہ مقامی کیشے کے پرانے ہونے کا امکان ہے، تو یہ مرکزی ذخیرے سے پورے کوڈ بیس کے لیے موجودہ کیشے کا سنیپ شاٹ ڈاؤن لوڈ کرتا ہے۔ اس کے بعد یہ اسنیپ شاٹ کا استعمال کرتے ہوئے ایک اضافی چیک کرتا ہے۔ اس نے mypy کی کارکردگی کو بڑھانے کی طرف ایک اور بڑا قدم اٹھایا ہے۔

یہ ڈراپ باکس میں ٹائپ چیکنگ کو تیز اور فطری اپنانے کا دور تھا۔ 2016 کے آخر تک، ہمارے پاس پہلے سے ہی قسم کی تشریحات کے ساتھ Python کوڈ کی تقریباً 420000 لائنیں تھیں۔ بہت سے صارفین قسم کی جانچ کے بارے میں پرجوش تھے۔ زیادہ سے زیادہ ترقیاتی ٹیمیں Dropbox mypy استعمال کر رہی تھیں۔

تب سب کچھ اچھا لگ رہا تھا، لیکن ہمیں ابھی بھی بہت کچھ کرنا تھا۔ ہم نے وقتاً فوقتاً صارف کے اندرونی سروے کرنا شروع کیے تاکہ پروجیکٹ کے مسائل والے علاقوں کی نشاندہی کی جا سکے اور یہ سمجھ سکیں کہ پہلے کن مسائل کو حل کرنے کی ضرورت ہے (یہ عمل آج بھی کمپنی میں استعمال ہوتا ہے)۔ سب سے اہم، جیسا کہ یہ واضح ہو گیا، دو کام تھے۔ سب سے پہلے، ہمیں کوڈ کی مزید قسم کی کوریج کی ضرورت تھی، دوسرا، ہمیں تیزی سے کام کرنے کے لیے mypy کی ضرورت تھی۔ یہ بالکل واضح تھا کہ mypy کو تیز کرنے اور اسے کمپنی کے منصوبوں میں لاگو کرنے کا ہمارا کام ابھی مکمل نہیں تھا۔ ہم، ان دونوں کاموں کی اہمیت سے پوری طرح واقف ہیں، ان کو حل کرنے کے لیے تیار ہیں۔

زیادہ پیداوری!

اضافی چیک نے mypy کو تیز تر بنا دیا، لیکن ٹول ابھی بھی کافی تیز نہیں تھا۔ بہت سے انکریمنٹل چیکس تقریباً ایک منٹ تک جاری رہے۔ اس کی وجہ سائیکلیکل امپورٹ تھی۔ یہ شاید کسی کو حیران نہیں کرے گا جس نے ازگر میں لکھے ہوئے بڑے کوڈ بیس کے ساتھ کام کیا ہے۔ ہمارے پاس سینکڑوں ماڈیولز کے سیٹ تھے، جن میں سے ہر ایک نے بالواسطہ طور پر باقی تمام کو درآمد کیا تھا۔ اگر امپورٹ لوپ میں کسی فائل کو تبدیل کیا گیا تھا تو، mypy کو اس لوپ میں موجود تمام فائلوں پر کارروائی کرنی پڑتی تھی، اور اکثر کوئی بھی ماڈیول جو اس لوپ سے ماڈیول درآمد کرتا ہے۔ ایسا ہی ایک چکر بدنام زمانہ "انحصار الجھاؤ" تھا جس نے ڈراپ باکس میں کافی پریشانی کا باعث بنا۔ ایک بار جب یہ ڈھانچہ کئی سو ماڈیولز پر مشتمل تھا، جب کہ اسے درآمد کیا گیا، بالواسطہ یا بالواسطہ، بہت سے ٹیسٹ، اسے پروڈکشن کوڈ میں بھی استعمال کیا گیا۔

ہم نے سرکلر انحصار کو "اٹللنگ" کرنے کے امکان پر غور کیا، لیکن ہمارے پاس ایسا کرنے کے لیے وسائل نہیں تھے۔ بہت زیادہ کوڈ تھا جس سے ہم واقف نہیں تھے۔ نتیجے کے طور پر، ہم ایک متبادل نقطہ نظر کے ساتھ آئے. ہم نے "انحصار الجھاؤ" کی موجودگی میں بھی mypy کو تیزی سے کام کرنے کا فیصلہ کیا۔ ہم نے یہ مقصد mypy ڈیمون کا استعمال کرتے ہوئے حاصل کیا۔ ڈیمون ایک سرور عمل ہے جو دو دلچسپ صلاحیتوں کو نافذ کرتا ہے۔ سب سے پہلے، یہ میموری میں پورے کوڈ بیس کے بارے میں معلومات محفوظ کرتا ہے۔ اس کا مطلب ہے کہ جب بھی آپ mypy چلاتے ہیں، آپ کو ہزاروں درآمد شدہ انحصار سے متعلق کیشڈ ڈیٹا لوڈ کرنے کی ضرورت نہیں ہوتی ہے۔ دوم، وہ احتیاط سے، چھوٹی ساختی اکائیوں کی سطح پر، افعال اور دیگر اداروں کے درمیان انحصار کا تجزیہ کرتا ہے۔ مثال کے طور پر، اگر فنکشن foo ایک فنکشن کو کال کرتا ہے۔ bar، پھر ایک انحصار ہے foo سے bar. جب کوئی فائل تبدیل ہوتی ہے، ڈیمون سب سے پہلے، تنہائی میں، صرف تبدیل شدہ فائل پر کارروائی کرتا ہے۔ اس کے بعد یہ اس فائل میں بیرونی طور پر نظر آنے والی تبدیلیوں کو دیکھتا ہے، جیسے تبدیل شدہ فنکشن دستخط۔ ڈیمون درآمدات کے بارے میں تفصیلی معلومات صرف ان فنکشنز کو چیک کرنے کے لیے استعمال کرتا ہے جو اصل میں ترمیم شدہ فنکشن کو استعمال کرتے ہیں۔ عام طور پر، اس نقطہ نظر کے ساتھ، آپ کو بہت کم افعال کو چیک کرنا پڑتا ہے۔

ان سب کو لاگو کرنا آسان نہیں تھا، کیونکہ اصل mypy نفاذ ایک وقت میں ایک فائل پر کارروائی کرنے پر بہت زیادہ توجہ مرکوز کرتا تھا۔ ہمیں بارڈر لائن کے بہت سے حالات سے نمٹنا پڑا، جس کے وقوع پذیر ہونے کے لیے بار بار جانچ پڑتال کی ضرورت تھی جہاں کوڈ میں کچھ تبدیل ہوا تھا۔ مثال کے طور پر، ایسا اس وقت ہوتا ہے جب کسی کلاس کو نئی بیس کلاس تفویض کی جاتی ہے۔ ایک بار جب ہم نے اپنی مرضی کے مطابق کام کر لیا، تو ہم زیادہ تر انکریمنٹل چیکس کے عمل کے وقت کو صرف چند سیکنڈ تک کم کرنے میں کامیاب ہو گئے۔ یہ ہمارے لیے ایک بڑی فتح معلوم ہوتی تھی۔

اس سے بھی زیادہ پیداوری!

ریموٹ کیشنگ کے ساتھ جس پر میں نے اوپر بات کی ہے، mypy ڈیمون نے تقریباً مکمل طور پر ان مسائل کو حل کر دیا جو اس وقت پیدا ہوتے ہیں جب ایک پروگرامر اکثر ٹائپ چیکنگ چلاتا ہے، جس سے فائلوں کی ایک چھوٹی سی تعداد میں تبدیلیاں آتی ہیں۔ تاہم، کم سے کم سازگار استعمال کے معاملے میں سسٹم کی کارکردگی اب بھی زیادہ سے زیادہ دور تھی۔ mypy کے صاف آغاز میں 15 منٹ سے زیادہ کا وقت لگ سکتا ہے۔ اور یہ اس سے کہیں زیادہ تھا جس سے ہم خوش ہوتے۔ ہر ہفتے صورتحال مزید خراب ہوتی گئی کیونکہ پروگرامرز نئے کوڈ لکھتے رہے اور موجودہ کوڈ میں تشریحات شامل کرتے رہے۔ ہمارے صارفین اب بھی زیادہ کارکردگی کے بھوکے تھے، لیکن ہم آدھے راستے سے ان سے مل کر خوش تھے۔

ہم نے mypy کے بارے میں پہلے کے خیالات میں سے ایک پر واپس جانے کا فیصلہ کیا۔ یعنی Python کوڈ کو C کوڈ میں تبدیل کرنا۔ Cython (ایک ایسا نظام جو آپ کو Python میں لکھے گئے کوڈ کو C کوڈ میں ترجمہ کرنے کی اجازت دیتا ہے) کے ساتھ تجربہ کرنے سے ہمیں کوئی واضح رفتار نہیں ملی، اس لیے ہم نے اپنے کمپائلر کو لکھنے کے خیال کو بحال کرنے کا فیصلہ کیا۔ چونکہ mypy codebase (Python میں لکھا ہوا) پہلے سے ہی تمام ضروری قسم کی تشریحات پر مشتمل ہے، اس لیے ہم نے سوچا کہ سسٹم کو تیز کرنے کے لیے ان تشریحات کو استعمال کرنے کی کوشش کرنا فائدہ مند ہوگا۔ میں نے اس خیال کو جانچنے کے لیے جلدی سے ایک پروٹو ٹائپ بنایا۔ اس نے مختلف مائیکرو بینچ مارکس پر کارکردگی میں 10 گنا سے زیادہ اضافہ دکھایا۔ ہمارا خیال Cython کا استعمال کرتے ہوئے Python ماڈیولز کو C ماڈیولز میں مرتب کرنا تھا، اور ٹائپ اینوٹیشنز کو رن ٹائم ٹائپ چیک میں تبدیل کرنا تھا (عام طور پر ٹائپ اینوٹیشنز کو رن ٹائم پر نظر انداز کیا جاتا ہے اور صرف ٹائپ چیکنگ سسٹم کے ذریعے استعمال کیا جاتا ہے)۔ ہم نے اصل میں Python سے mypy کے نفاذ کو ایک ایسی زبان میں ترجمہ کرنے کا منصوبہ بنایا تھا جسے statically ٹائپ کرنے کے لیے ڈیزائن کیا گیا تھا، جو بالکل Python کی طرح نظر آئے گا (اور زیادہ تر کام کے لیے)۔ (اس قسم کی مختلف زبانوں کی منتقلی mypy پروجیکٹ کی ایک روایت بن گئی ہے۔ اصل mypy نفاذ الور میں لکھا گیا تھا، پھر جاوا اور Python کا ایک مصنوعی ہائبرڈ تھا)۔

CPython ایکسٹینشن API پر توجہ مرکوز کرنا پروجیکٹ مینجمنٹ کی صلاحیتوں سے محروم نہ ہونے کی کلید تھی۔ ہمیں کسی ورچوئل مشین یا کسی لائبریری کو لاگو کرنے کی ضرورت نہیں تھی جس کی mypy کو ضرورت تھی۔ اس کے علاوہ، ہمارے پاس اب بھی مکمل Python ایکو سسٹم اور تمام ٹولز (جیسے pytest) تک رسائی ہوگی۔ اس کا مطلب یہ تھا کہ ہم ترقی کے دوران تشریح شدہ Python کوڈ کا استعمال جاری رکھ سکتے ہیں، جس سے ہمیں کوڈ کے مرتب ہونے کا انتظار کرنے کے بجائے کوڈ میں تبدیلیاں کرنے اور اس کی جانچ کرنے کے بہت تیز پیٹرن کے ساتھ کام جاری رکھنے کی اجازت ملتی ہے۔ ایسا لگتا تھا کہ ہم دو کرسیوں پر بیٹھ کر بہت اچھا کام کر رہے ہیں، تو بات کرنے کے لیے، اور ہمیں یہ پسند آیا۔

کمپائلر، جسے ہم نے mypyc کہا (چونکہ یہ قسم کے تجزیہ کے لیے mypy کو فرنٹ اینڈ کے طور پر استعمال کرتا ہے)، ایک بہت کامیاب پروجیکٹ نکلا۔ مجموعی طور پر، ہم نے کیشنگ کے بغیر اکثر mypy رنز کے لیے تقریباً 4x اسپیڈ اپ حاصل کیا۔ mypyc پروجیکٹ کے بنیادی حصے کو تیار کرنے میں مائیکل سلیوان، ایوان لیوکیوسکی، ہیو ہان، اور خود کی ایک چھوٹی ٹیم نے تقریباً 4 کیلنڈر مہینے لگائے۔ کام کی یہ مقدار اس سے بہت کم تھی جو mypy کو دوبارہ لکھنے کے لیے درکار ہوتی تھی، مثال کے طور پر، C++ یا Go میں۔ اور ہمیں پروجیکٹ میں بہت کم تبدیلیاں کرنی پڑیں جتنی ہمیں دوسری زبان میں دوبارہ لکھتے وقت کرنی پڑیں گی۔ ہم نے یہ بھی امید ظاہر کی کہ ہم mypyc کو اس سطح پر لا سکتے ہیں کہ دوسرے ڈراپ باکس پروگرامرز اسے اپنے کوڈ کو مرتب کرنے اور تیز کرنے کے لیے استعمال کر سکیں۔

کارکردگی کی اس سطح کو حاصل کرنے کے لیے، ہمیں انجینئرنگ کے کچھ دلچسپ حل استعمال کرنے تھے۔ اس طرح، کمپائلر تیز، نچلے درجے کی C تعمیرات کا استعمال کر کے بہت سے کاموں کو تیز کر سکتا ہے۔ مثال کے طور پر، ایک مرتب شدہ فنکشن کال کو C فنکشن کال میں ترجمہ کیا جاتا ہے۔ اور اس طرح کی کال ایک تشریح شدہ فنکشن کو کال کرنے سے کہیں زیادہ تیز ہے۔ کچھ آپریشنز، جیسے لغت کی تلاش، اب بھی CPython سے باقاعدہ C-API کالز کا استعمال کرتے ہوئے شامل ہیں، جو مرتب ہونے پر صرف معمولی تیز تھیں۔ ہم تشریح کے ذریعہ بنائے گئے نظام پر اضافی بوجھ کو ختم کرنے کے قابل تھے، لیکن اس معاملے میں کارکردگی کے لحاظ سے صرف ایک چھوٹا سا فائدہ ہوا۔

سب سے عام "سست" کارروائیوں کی نشاندہی کرنے کے لیے، ہم نے کوڈ پروفائلنگ کی۔ اس ڈیٹا سے لیس، ہم نے یا تو mypyc کو موافقت کرنے کی کوشش کی تاکہ یہ اس طرح کے آپریشنز کے لیے تیز تر C کوڈ تیار کرے، یا تیز تر آپریشنز کا استعمال کرتے ہوئے متعلقہ Python کوڈ کو دوبارہ لکھے (اور بعض اوقات ہمارے پاس اس یا دوسرے مسئلے کا آسان حل نہیں ہوتا تھا) . Python کوڈ کو دوبارہ لکھنا اکثر اس مسئلے کا آسان حل ہوتا تھا کہ مرتب کرنے والے کو خود بخود وہی تبدیلی انجام دینے سے۔ طویل مدتی میں، ہم ان میں سے بہت سی تبدیلیوں کو خودکار بنانا چاہتے تھے، لیکن اس وقت ہماری توجہ کم سے کم کوشش کے ساتھ mypy کو تیز کرنے پر تھی۔ اور اس مقصد کی طرف بڑھتے ہوئے، ہم نے کئی کونوں کو کاٹ دیا۔

جاری رکھنا ...

پیارے قارئین! mypy پروجیکٹ کے بارے میں آپ کے کیا تاثرات تھے جب آپ کو اس کے وجود کا علم ہوا؟

Python کوڈ کی 4 ملین لائنوں کو ٹائپ چیک کرنے کا راستہ۔ حصہ 2
Python کوڈ کی 4 ملین لائنوں کو ٹائپ چیک کرنے کا راستہ۔ حصہ 2

ماخذ: www.habr.com

نیا تبصرہ شامل کریں