Code Velocity
ڈیولپر ٹولز

ڈف لائنز کی کارکردگی: بہتر بنانے کے لیے گٹ ہب کی دشوار گزار چڑھائی

·7 منٹ پڑھنے·GitHub·اصل ماخذ
شیئر کریں
گٹ ہب ڈف لائنز میں کارکردگی میں بہتری کو ظاہر کرنے والا خاکہ، جس میں بہتر منظر میں کم شدہ DOM نوڈس اور جاوا اسکرپٹ ہیپ کو نمایاں کیا گیا ہے۔

گٹ ہب کی دشوار گزار چڑھائی: بہترین کارکردگی کے لیے ڈف لائنز کو بہتر بنانا

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

ان آپٹیمائزیشنز سے پہلے، اگرچہ زیادہ تر صارفین ایک رسپانسو تجربے سے لطف اندوز ہوتے تھے، لیکن بڑی پل ریکویسٹس ناگزیر طور پر کارکردگی میں نمایاں کمی کا باعث بنتی تھیں۔ انتہائی معاملات میں جاوا اسکرپٹ ہیپ 1 جی بی سے تجاوز کر جاتی تھی، DOM نوڈز کی تعداد 400,000 سے زیادہ ہو جاتی تھی، اور صفحہ کے تعاملات شدید طور پر سست یا حتیٰ کہ ناقابل استعمال ہو جاتے تھے۔ انٹریکشن ٹو نیکسٹ پینٹ (INP) جیسے اہم رسپانسوپنیس میٹرکس قابل قبول سطح سے اوپر چلے جاتے تھے، جس سے صارفین کے لیے ان پٹ لیگ کا ایک ٹھوس احساس پیدا ہوتا تھا۔ یہ مضمون گٹ ہب کے اس تفصیلی سفر کی گہرائی میں جاتا ہے جس میں ان بنیادی کارکردگی میٹرکس کو ڈرامائی طور پر بہتر بنایا گیا، جس سے ڈف ریویو کے تجربے میں تبدیلی آئی۔

کارکردگی کی رکاوٹوں کو نیویگیٹ کرنا: ایک کثیر حکمت عملی کا نقطہ نظر

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

اس کے بجائے، گٹ ہب کی انجینئرنگ ٹیم نے حکمت عملیوں کا ایک جامع سیٹ تیار کیا، جن میں سے ہر ایک کو پل ریکویسٹ کے مخصوص سائز اور پیچیدگیوں کو حل کرنے کے لیے محتاط طور پر ڈیزائن کیا گیا تھا۔ یہ حکمت عملی تین بنیادی موضوعات پر مبنی تھیں:

  1. ڈف لائن کمپونینٹس کے لیے مرکوز آپٹیمائزیشنز: زیادہ تر پل ریکویسٹس کے لیے بنیادی ڈف تجربے کی کارکردگی کو بڑھانا۔ اس سے یہ یقینی بنایا گیا کہ درمیانے اور بڑے جائزے مقامی فائنڈ اِن پیج جیسی متوقع فعالیتوں سے سمجھوتہ کیے بغیر تیز رہیں۔
  2. ورچوئلائزیشن کے ساتھ شائستہ تنزلی: سب سے بڑی پل ریکویسٹس کے لیے استعمال کو یقینی بنانا جس میں رسپانسوپنیس اور استحکام کو ترجیح دی گئی، اور ذہانت سے اس مواد کو محدود کرنا جو کسی بھی وقت رینڈر ہوتا ہے۔
  3. بنیادی اجزاء اور رینڈرنگ کی بہتری میں سرمایہ کاری: ایسی اصلاحات نافذ کرنا جو صارف کے مخصوص دیکھنے کے موڈ سے قطع نظر، ہر پل ریکویسٹ کے سائز میں مشترکہ فوائد فراہم کریں۔

ان اسٹریٹجک ستونوں نے ٹیم کی کوششوں کی رہنمائی کی، جس سے انہیں کارکردگی کے مسائل کی بنیادی وجوہات سے منظم طریقے سے نمٹنے اور بعد کی آرکیٹیکچرل اصلاحات کے لیے راستہ ہموار کرنے کا موقع ملا۔

V1 کا تجزیہ: ایک مہنگی ڈف لائن کی قیمت

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

v1 میں، ہر ڈف لائن کو رینڈر کرنا ایک مہنگا عمل تھا۔ متحد ویو میں ایک لائن عام طور پر تقریباً 10 DOM عناصر میں تبدیل ہوتی تھی، جبکہ ایک اسپلٹ ویو میں 15 کے قریب کی ضرورت ہوتی تھی۔ یہ تعداد نحو کو نمایاں کرنے کے ساتھ مزید بڑھ جاتی تھی، جس میں بہت سے مزید <span> ٹیگ شامل ہوتے تھے۔ ری ایکٹ پرت پر، متحد ڈفس میں فی لائن کم از کم آٹھ کمپونینٹس ہوتے تھے، اور اسپلٹ ویوز میں کم از کم 13۔ یہ بنیادی تعدادیں تھیں، جن میں اضافی UI اسٹیٹس جیسے تبصرے، ہور، اور فوکس مزید کمپونینٹس کا اضافہ کرتے تھے۔

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

خلاصہ کے طور پر، ہر v1 ڈف لائن کے لیے، سسٹم میں تھا:

  • کم از کم 10-15 DOM ٹری عناصر
  • کم از کم 8-13 ری ایکٹ کمپونینٹس
  • کم از کم 20 ری ایکٹ ایونٹ ہینڈلرز
  • بے شمار چھوٹے، دوبارہ قابل استعمال ری ایکٹ کمپونینٹس

اس آرکیٹیکچر نے بڑے پل ریکویسٹ سائز کو سست INP اور جاوا اسکرپٹ ہیپ کے زیادہ استعمال سے براہ راست منسلک کیا، جس کے لیے ایک بنیادی از سر نو جانچ اور دوبارہ ڈیزائن کی ضرورت تھی۔

رینڈرنگ میں انقلاب: V2 آپٹیمائزیشنز کا اثر

v2 کی طرف منتقلی نے ایک اہم آرکیٹیکچرل اوور ہال کی نشاندہی کی، جس میں دانے دار، مؤثر تبدیلیوں پر توجہ مرکوز کی گئی۔ ٹیم نے اس فلسفے کو اپنایا کہ 'جب کارکردگی کی بات آتی ہے، خاص طور پر پیمانے پر، تو کوئی بھی تبدیلی بہت چھوٹی نہیں ہوتی۔' ایک بہترین مثال لائن نمبر سیلز سے غیر ضروری <code> ٹیگز کو ہٹانا تھا۔ اگرچہ فی ڈف لائن میں دو DOM نوڈز کو کم کرنا معمولی لگ سکتا ہے، لیکن 10,000 لائنوں میں، یہ فوری طور پر DOM میں 20,000 کم نوڈز کے برابر تھا، جو یہ ظاہر کرتا ہے کہ ہدف شدہ، تدریجی آپٹیمائزیشنز کس طرح خاطر خواہ بہتری لاتی ہیں۔

نیچے دیا گیا بصری موازنہ کمپوننٹ کی سطح پر v1 سے v2 تک کی کم پیچیدگی کو نمایاں کرتا ہے:

V1 Diff Components and HTML. We had 8 react components for a single diff line. V2 Diff Components and HTML. We had 3 react components for a single diff line.

ہموار کمپوننٹ آرکیٹیکچر

v2 میں ایک بنیادی جدت کمپوننٹ ٹری کو آسان بنانا تھا۔ ٹیم فی ڈف لائن میں آٹھ ری ایکٹ کمپونینٹس سے کم ہو کر دو پر آ گئی۔ یہ گہری نیسٹڈ کمپوننٹ ٹریز کو ختم کرکے اور ہر اسپلٹ اور یونیفائیڈ ڈف لائن کے لیے مخصوص کمپونینٹس بنا کر حاصل کیا گیا، یہاں تک کہ کچھ کوڈ کی نقل کے ساتھ بھی۔ ایونٹ ہینڈلنگ کو بھی مرکزی بنایا گیا، اب اسے data-attribute اقدار کا استعمال کرتے ہوئے ایک واحد ٹاپ لیول ہینڈلر کے ذریعے منظم کیا جاتا ہے، جس نے v1 کے متعدد انفرادی ایونٹ ہینڈلرز کی جگہ لی۔ اس نقطہ نظر نے کوڈ اور کارکردگی دونوں کو ڈرامائی طور پر ہموار کیا۔

ذہین اسٹیٹ مینجمنٹ اور O(1) ڈیٹا تک رسائی

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

مزید برآں، v2 نے O(n) لوک اپس اور ضرورت سے زیادہ useEffect ہکس کے مسئلے کو حل کیا جو v1 کو متاثر کرتے تھے۔ ٹیم نے دو حصوں پر مشتمل حکمت عملی اپنائی: useEffect کے استعمال کو ڈف فائلوں کے ٹاپ لیول تک سختی سے محدود کرنا اور لائن ریپنگ کمپونینٹس میں ان کے دوبارہ تعارف کو روکنے کے لیے لِنٹنگ قواعد قائم کرنا۔ اس سے درست میموائزیشن اور پیش قیاسی رویے کو یقینی بنایا گیا۔ اس کے ساتھ ساتھ، عالمی اور ڈف اسٹیٹ مشینوں کو JavaScript Map آبجیکٹس کا استعمال کرتے ہوئے O(1) مستقل وقت کے لوک اپس کو استعمال کرنے کے لیے دوبارہ ڈیزائن کیا گیا۔ اس نے لائن سلیکشن اور کمنٹ مینجمنٹ جیسے عام کارروائیوں کے لیے تیز، مستقل سلیکٹرز کی اجازت دی، جس سے کوڈ کے معیار میں نمایاں اضافہ ہوا، کارکردگی میں بہتری آئی، اور فلیٹڈ، میپڈ ڈیٹا ڈھانچے کو برقرار رکھ کر پیچیدگی میں کمی آئی۔ ڈیولپر ورک فلو کو بہتر بنانے اور بنیادی آرکیٹیکچر کے لیے یہ محتاط نقطہ نظر ایک مضبوط، قابل توسیع نظام کو یقینی بناتا ہے۔

قابل پیمائش اثر: V2 نے قابل مقدار فوائد فراہم کیے

v2 میں نافذ کی گئی محتاط آرکیٹیکچرل اور کوڈ لیول کی آپٹیمائزیشنز نے کارکردگی کے اہم میٹرکس میں گہری، قابل مقدار بہتری حاصل کی۔ نیا نظام نمایاں طور پر تیزی سے چلتا ہے، جس میں جاوا اسکرپٹ ہیپ کے استعمال اور INP سکور میں بڑے پیمانے پر کمی آئی ہے۔ درج ذیل جدول ایک نمائندہ پل ریکویسٹ پر دیکھی گئی ڈرامائی بہتری کو ظاہر کرتا ہے جس میں 10,000 لائن تبدیلیاں اسپلٹ ڈف سیٹنگ میں شامل ہیں:

میٹرکv1v2بہتری
جاوا اسکرپٹ ہیپ1GB+250MB75%
DOM نوڈس400,000+80,00080%
INP p951000ms+100ms90%

یہ اعداد و شمار گٹ ہب کی کثیر جہتی حکمت عملی کی کامیابی کی نشاندہی کرتے ہیں۔ جاوا اسکرپٹ ہیپ کے سائز میں 75% کمی اور DOM نوڈس میں 80% کمی نہ صرف ایک ہلکے براؤزر کے نشان میں ترجمہ کرتی ہے بلکہ براہ راست ایک زیادہ مستحکم اور رسپانسو انٹرفیس میں بھی حصہ ڈالتی ہے۔ سب سے حیرت انگیز بہتری، INP p95 (تعامل کی لیٹینسی کے 95 ویں پرسنٹائل) میں 90% کمی، کا مطلب ہے کہ 95% صارف تعاملات اب صرف 100 ملی سیکنڈ کے اندر مکمل ہوتے ہیں، عملی طور پر ان پٹ لیگ کو ختم کرتے ہیں جس نے v1 میں بڑی پل ریکویسٹس کو متاثر کیا تھا۔ اس سے صارف کا تجربہ نمایاں طور پر بہتر ہوتا ہے، جس سے بڑے کوڈ ریویوز چھوٹے ریویوز کی طرح ہموار اور رسپانسو محسوس ہوتے ہیں۔

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

اکثر پوچھے جانے والے سوالات

What is the 'Files changed' tab in GitHub pull requests and why was its performance critical?
The 'Files changed' tab is a core component of GitHub's pull request workflow, allowing engineers to review code modifications. Its performance is critical because it's where developers spend significant time, and slowdowns, especially with large pull requests, can severely impede productivity and user experience. GitHub prioritized its optimization to ensure responsiveness across all scales of code changes, from minor fixes to extensive refactorings, which can involve millions of lines across thousands of files. Maintaining a smooth and efficient review process is paramount for collaborative development.
What were the primary performance challenges GitHub faced with large pull requests in the v1 architecture?
In its initial React-based architecture (v1), GitHub encountered significant performance degradation when handling large pull requests. Key issues included the JavaScript heap exceeding 1 GB, DOM node counts soaring past 400,000, and page interactions becoming extremely sluggish or even unusable. The Interaction to Next Paint (INP) metric, which measures responsiveness, showed unacceptably high values. These problems stemmed from an inefficient rendering strategy where each diff line was resource-intensive, with too many DOM elements, React components, and event handlers, particularly in cases involving thousands of lines of code.
How did GitHub approach solving the complex performance issues, moving beyond a 'silver bullet' solution?
Recognizing that no single solution would address the diverse range of pull request sizes and complexities, GitHub adopted a multi-faceted strategic approach. They focused on three core themes: targeted optimizations for diff-line components to keep medium and large reviews fast, graceful degradation with virtualization to maintain usability for the largest pull requests by limiting rendered content, and investing in foundational components and rendering improvements to yield compounding benefits across all pull request sizes. This comprehensive strategy allowed them to tailor solutions to specific problem areas.
What were the key limitations of the 'v1' diff rendering architecture that made it unsustainable for scale?
The v1 architecture, while initially sensible for smaller diffs, proved unsustainable for large-scale pull requests. Each diff line was costly, requiring 10-15 DOM elements, 8-13 React components, and over 20 event handlers. This was compounded by deep component nesting, excessive `useEffect` hooks, and O(n) data lookups, leading to unnecessary re-renders and increased complexity. The abstraction layers, meant to share code, inadvertently added overhead by carrying logic for both split and unified views, even when only one was active. This design led to a significant increase in JavaScript heap, DOM count, and poor INP scores for larger diffs.
What specific architectural changes were implemented in 'v2' to drastically improve diff line performance?
The v2 architecture introduced several critical changes. It streamlined the component tree, reducing React components per diff line from eight to two by creating dedicated components for split and unified views, even with some code duplication. Event handling was centralized to a single top-level handler using `data-attribute` values, replacing numerous individual handlers. Complex app state, such as commenting features, was moved into conditionally rendered child components, ensuring that diff lines primarily focused on rendering code. Furthermore, v2 restricted `useEffect` hooks to top-level diff files and adopted O(1) constant-time data access using `JavaScript Map` for efficient state lookups, significantly reducing re-renders and improving data management.
How did the GitHub engineering team achieve quantifiable improvements in JavaScript heap, DOM nodes, and INP metrics with v2?
The cumulative effect of v2's architectural changes led to substantial quantifiable improvements. For a pull request with 10,000 line changes, the JavaScript heap size was reduced from 1GB+ to 250MB, a 75% improvement. DOM nodes decreased from 400,000+ to 80,000, an 80% reduction. The Interaction to Next Paint (INP) p95 (95th percentile) saw an astounding 90% improvement, dropping from 1000ms+ to just 100ms. These results were achieved through meticulous optimization, including removing extraneous DOM elements, simplifying the React component structure, centralizing event handling, and optimizing state management and data access patterns, leading to a much faster and more responsive user experience.
What is Interaction to Next Paint (INP) and why is its improvement significant for GitHub's user experience?
Interaction to Next Paint (INP) is a crucial web performance metric that assesses a page's responsiveness by measuring the latency of all interactions made by a user with the page. It records the time from when a user interacts (e.g., click, tap, keypress) until the next frame is painted to the screen, reflecting the visual feedback of that interaction. For GitHub, a high INP meant users experienced noticeable input lag, making the platform feel slow and unresponsive. By reducing INP p95 from over 1000ms to 100ms in v2, GitHub significantly enhanced the perceived speed and fluidity of the 'Files changed' tab, ensuring a smoother and more satisfying developer experience, especially during code review.

اپ ڈیٹ رہیں

تازہ ترین AI خبریں اپنے ان باکس میں حاصل کریں۔

شیئر کریں