GitHub-ın Çətin Mübarizəsi: Maksimal Performans üçün Diff Sətirlərini Optimallaşdırma
Pull sorğuları GitHub-ın canlı nüvəsini təşkil edir, burada saysız-hesabsız mühəndislər peşəkar həyatlarının əhəmiyyətli bir hissəsini həsr edirlər. GitHub-ın böyük miqyasını nəzərə alsaq, kiçik bir sətirlik düzəlişlərdən minlərlə faylı və milyonlarla sətiri əhatə edən nəhəng dəyişikliklərə qədər dəyişən pull sorğularını idarə edərkən, nəzərdən keçirmə təcrübəsi olduqca sürətli və həssas qalmalıdır. Bütün istifadəçilər üçün hazırda standart olan Dəyişdirilmiş fayllar sekmesi üçün yeni React-əsaslı təcrübənin yaxınlarda tətbiqi, xüsusilə bu çətin böyük pull sorğuları üçün möhkəm performans təmin etməkdə əsaslı bir sərmayə oldu. Bu öhdəlik, optimallaşdırılmış render, qarşılıqlı təsir gecikməsi və yaddaş istehlakı kimi çətin problemləri ardıcıl şəkildə həll etməyi əhatə edirdi.
Bu optimallaşdırmalardan əvvəl, əksər istifadəçilər həssas bir təcrübədən faydalansa da, böyük pull sorğuları qaçılmaz olaraq nəzərəçarpacaq performans geriləməsinə səbəb olurdu. Həddindən artıq hallarda JavaScript heap 1 GB-ı keçir, DOM düyünlərinin sayı 400,000-i ötür və səhifə qarşılıqlı təsirləri həddindən artıq yavaş və ya hətta istifadəyə yararsız olurdu. Növbəti Rəsmə Qarşılıqlı Təsir (INP) kimi əsas cavabdehlik göstəriciləri qəbuledilən səviyyələri aşaraq istifadəçilər üçün nəzərəçarpacaq bir giriş gecikməsi hissi yaradırdı. Bu məqalə, GitHub-ın bu əsas performans göstəricilərini əhəmiyyətli dərəcədə yaxşılaşdırmaq və diff nəzərdən keçirmə təcrübəsini dəyişdirmək üçün atdığı detallı yolu araşdırır.
Performans Darboğazlarını İdarəetmə: Çoxstrategiyalı Yanaşma
Dəyişdirilmiş fayllar sekmesinin performans araşdırmasına başlarkən, tək bir 'gümüş güllə' həllinin kifayət etməyəcəyi tez bir zamanda aydın oldu. Hər bir xüsusiyyəti və brauzer-yerli davranışı qorumaq üçün nəzərdə tutulmuş texnikalar, ekstremal məlumat yükləri ilə tez-tez bir sərhədə çatırdı. Əksinə, yalnız ən pis ssenarilərin qarşısını almağa yönəlmiş yumşaltmalar, gündəlik nəzərdən keçirmələr üçün əlverişsiz kompromislər yarada bilərdi.
Bunun əvəzinə, GitHub-ın mühəndislik komandası hər biri pull sorğularının xüsusi ölçülərini və mürəkkəbliklərini həll etmək üçün diqqətlə hazırlanmış hərtərəfli strategiyalar dəsti inkişaf etdirdi. Bu strategiyalar üç əsas mövzu üzərində qurulmuşdu:
- Diff-Sətir Komponentləri üçün Hədəflənmiş Optimallaşdırmalar: Pull sorğularının əksəriyyəti üçün əsas diff təcrübəsinin səmərəliliyini artırmaq. Bu, yerli səhifədə axtarış kimi gözlənilən funksionallıqlardan ödün vermədən orta və böyük nəzərdən keçirmələrin sürətli qalmasını təmin etdi.
- Virtualizasiya ilə Zərif Pisləşmə: Həssaslığı və sabitliyi prioritetləşdirərək, hər hansı bir anda render edilmiş məzmunu ağıllı şəkildə məhdudlaşdıraraq ən böyük pull sorğuları üçün istifadə qabiliyyətini təmin etmək.
- Əsas Komponentlərə və Render Yaxşılaşdırmalarına Sərmayə: İstifadəçinin xüsusi baxış rejimindən asılı olmayaraq, hər bir pull sorğusu ölçüsü üzrə əlavə faydalar gətirən yaxşılaşdırmaların tətbiqi.
Bu strateji sütunlar komandanın səylərinə rəhbərlik etdi, onlara performans problemlərinin kök səbəblərini sistemli şəkildə həll etməyə və sonrakı memarlıq təkmilləşdirmələri üçün zəmin yaratmağa imkan verdi.
V1-i Dekonstruksiya Etmək: Bahalı Diff Sətrinin Qiyməti
GitHub-ın ilkin React-əsaslı tətbiqi, v1 olaraq adlandırılan, müasir diff görünüşü üçün zəmin yaratdı. Bu versiya, klassik Rails görünüşünü React-ə köçürmək, kiçik, təkrar istifadə oluna bilən React komponentləri yaratmağı və aydın bir DOM ağac quruluşunu qorumağı prioritetləşdirən səmimi bir səy idi. Lakin, bu yanaşma, başlanğıcda məntiqli olsa da, miqyasda əhəmiyyətli bir darboğaz olduğunu sübut etdi.
v1-də hər diff sətrinin render edilməsi bahalı bir əməliyyat idi. Birləşdirilmiş görünüşdə bir tək sətir tipik olaraq təxminən 10 DOM elementinə çevrilirdi, split görünüş isə 15-ə yaxın tələb edirdi. Bu say sintaksis vurğulama ilə daha da artır, daha çox <span> teqləri əlavə edirdi. React qatında, birləşdirilmiş diff-lər hər sətir üçün ən az səkkiz komponentdən, split görünüşlər isə minimum 13-dən ibarət idi. Bunlar baza sayları idi, şərhlər, üzərinə gəlmə və fokus kimi əlavə UI vəziyyətləri daha da çox komponent əlavə edirdi.
v1 memarlığı həmçinin React hadisə işləyicilərinin çoxalmasından əziyyət çəkirdi. Kiçik miqyasda zərərsiz görünsə də, tək bir diff sətri 20 və ya daha çox hadisə işləyicisi daşıya bilərdi. Böyük bir pull sorğusunda minlərlə sətir üzrə çoxaldıqda, bu tez bir zamanda yığılaraq həddindən artıq yükə və artan JavaScript heap istifadəsinə səbəb olurdu. Bu mürəkkəblik yalnız performansa təsir etmədi, həm də inkişaf və baxımı daha çətinləşdirdi. Məhdud məlumatlar üçün effektiv olan ilkin dizayn, GitHub-ın müxtəlif pull sorğusu ölçülərinin məhdudiyyətsiz təbiəti ilə üzləşdikdə əhəmiyyətli dərəcədə çətinlik çəkdi.
Xülasə, hər v1 diff sətri üçün sistemdə var idi:
- Minimum 10-15 DOM ağac elementi
- Minimum 8-13 React Komponent
- Minimum 20 React Hadisə İşləyicisi
- Çoxsaylı kiçik, təkrar istifadə oluna bilən React Komponentləri
Bu memarlıq, daha böyük pull sorğusu ölçülərini daha yavaş INP və artan JavaScript heap istifadəsi ilə birbaşa əlaqələndirdi, bu da əsaslı yenidən qiymətləndirmə və yenidən dizaynı zəruri etdi.
Renderləməni İnqilab Etmək: V2 Optimallaşdırmalarının Təsiri
v2-yə keçid, dənəvər, təsirli dəyişikliklərə fokuslanan əhəmiyyətli bir memarlıq yeniləməsi oldu. Komanda 'performans mövzusunda, xüsusilə miqyasda, heç bir dəyişiklik çox kiçik deyil' fəlsəfəsini mənimsədi. Əsas nümunə, sətir nömrəsi hüceyrələrindən lazımsız <code> teqlərinin çıxarılması idi. Hər diff sətri üçün iki DOM düyününü atmaq kiçik görünə bilsə də, 10,000 sətir üzrə bu, dərhal DOM-da 20,000 daha az düyünə bərabər idi, bu da hədəflənmiş, artan optimallaşdırmaların necə əhəmiyyətli yaxşılaşmalara səbəb olduğunu göstərdi.
Aşağıdakı vizual müqayisə v1-dən v2-yə komponent səviyyəsində azaldılmış mürəkkəbliyi vurğulayır:

Sadələşdirilmiş Komponent Memarlığı
v2-də əsas yenilik, komponent ağacını sadələşdirməyi əhatə edirdi. Komanda hər diff sətri üçün səkkiz React komponentindən ikiyə endirildi. Bu, dərin yuvalanmış komponent ağaclarını aradan qaldırmaq və hər split və birləşdirilmiş diff sətri üçün xüsusi komponentlər yaratmaqla əldə edildi. Bu, bəzi kod təkrarlarını ortaya çıxarsa da, məlumat girişini kəskin şəkildə sadələşdirdi və ümumi mürəkkəbliyi azaltdı. Hadisə idarəetməsi də mərkəzləşdirildi, indi v1-in çoxsaylı fərdi hadisə işləyicilərini əvəz edərək data-attribute dəyərlərindən istifadə edən tək bir yuxarı səviyyəli işləyici tərəfindən idarə olunur. Bu yanaşma həm kodu, həm də performansı kəskin şəkildə sadələşdirdi.
Ağıllı Vəziyyət İdarəetməsi və O(1) Məlumat Girişi
Bəlkə də ən təsirli dəyişiklik, şərh və kontekst menyuları kimi mürəkkəb tətbiq vəziyyətini şərti olaraq render edilmiş uşaq komponentlərinə köçürmək idi. GitHub kimi bir mühitdə, pull sorğuları minlərlə sətiri keçə bildiyi halda, yalnız kiçik bir hissəsi şərhə sahib olacağı zaman hər bir sətrin mürəkkəb şərh vəziyyətini daşıması səmərəsizdir. Bu vəziyyəti yuvalanmış komponentlərə köçürməklə, diff-sətir komponentinin əsas məsuliyyəti sırf kod render edilməsi oldu, bu da Tək Məsuliyyət Prinsipi ilə uzlaşırdı.
Bundan əlavə, v2 v1-i narahat edən O(n) axtarışları və həddindən artıq useEffect qarmaqları problemini həll etdi. Komanda iki hissəli bir strategiya qəbul etdi: useEffect istifadəsini diff fayllarının yuxarı səviyyəsi ilə ciddi şəkildə məhdudlaşdırmaq və sətir bükən komponentlərdə onların yenidən tətbiqinin qarşısını almaq üçün linting qaydaları yaratmaq. Bu, dəqiq memoizasiyanı və proqnozlaşdırıla bilən davranışı təmin etdi. Eyni zamanda, qlobal və diff vəziyyət maşınları, JavaScript Map obyektlərindən istifadə edərək O(1) sabit zamanlı axtarışlardan faydalanmaq üçün yenidən dizayn edildi. Bu, sətir seçimi və şərh idarəetməsi kimi ümumi əməliyyatlar üçün sürətli, ardıcıl seçicilərə imkan verdi, kod keyfiyyətini əhəmiyyətli dərəcədə artırdı, performansı yaxşılaşdırdı və düzəldilmiş, xəritələnmiş məlumat strukturlarını qoruyaraq mürəkkəbliyi azaltdı. İnkişafçı iş axınlarının optimallaşdırılması və əsas memarlıq üçün bu dəqiq yanaşma möhkəm, miqyaslana bilən bir sistem təmin edir.
Ölçülə Bilən Təsir: V2 Kəmiyyətcə Ölçülə Bilən Qazanclar Gətirir
v2-də tətbiq edilmiş dəqiq memarlıq və kod səviyyəsində optimallaşdırmalar, əsas performans göstəricilərində dərin, kəmiyyətcə ölçülə bilən yaxşılaşmalar verdi. Yeni sistem, JavaScript heap istifadəsində və INP nəticələrində böyük azalma ilə əhəmiyyətli dərəcədə sürətli işləyir. Aşağıdakı cədvəl, split diff şəraitində 10,000 sətir dəyişikliyi olan tipik bir pull sorğusu üzərində müşahidə olunan dramatik yaxşılaşmaları göstərir:
| Metrik | v1 | v2 | Yaxşılaşma |
|---|---|---|---|
| JavaScript Heap | 1GB+ | 250MB | 75% |
| DOM Düyünləri | 400,000+ | 80,000 | 80% |
| INP p95 | 1000ms+ | 100ms | 90% |
Bu rəqəmlər GitHub-ın çoxşaxəli strategiyasının uğurunu vurğulayır. JavaScript heap ölçüsündə 75% azalma və DOM düyünlərində 80% azalma yalnız daha yüngül brauzer izi demək deyil, həm də daha sabit və həssas interfeysə birbaşa töhfə verir. Ən təsirli yaxşılaşma, INP p95-də (qarşılıqlı təsir gecikməsinin 95-ci persentili) 90% azalma, istifadəçi qarşılıqlı təsirlərinin 95%-nin indi cəmi 100 millisaniyə ərzində tamamlandığı deməkdir ki, bu da v1-də böyük pull sorğularını narahat edən giriş gecikməsini demək olar ki, aradan qaldırır. Bu, istifadəçi təcrübəsini əhəmiyyətli dərəcədə artırır, böyük kod nəzərdən keçirmələrini daha kiçik olanlar qədər axıcı və həssas hiss etdirir.
GitHub-ın davamlı təkmilləşdirməyə olan öhdəliyi, diff-sətir optimallaşdırılmasına bu dərin yanaşma ilə sübut olunduğu kimi, onların dünya səviyyəli tərtibatçı platforması təmin etməyə olan sədaqətinin göstəricisidir. Performans darboğazlarını ciddi şəkildə təhlil edərək və hədəflənmiş memarlıq həlləri tətbiq etməklə, onlar yalnız kritik miqyaslana bilirlik problemlərini həll etmədilər, həm də əsas məhsullarında həssaslıq üçün yeni bir standart təyin etdilər. Performansa bu diqqət, mühəndislərin kod nəzərdən keçirmələri kimi vacib vəzifələrlə səmərəli şəkildə məşğul olmasını təmin edir, nəticədə daha yüksək kod keyfiyyəti və təhlükəsizliyi və daha məhsuldar inkişaf mühiti yaradır.
Orijinal mənbə
https://github.blog/engineering/architecture-optimization/the-uphill-climb-of-making-diff-lines-performant/Tez-tez Verilən Suallar
What is the 'Files changed' tab in GitHub pull requests and why was its performance critical?
What were the primary performance challenges GitHub faced with large pull requests in the v1 architecture?
How did GitHub approach solving the complex performance issues, moving beyond a 'silver bullet' solution?
What were the key limitations of the 'v1' diff rendering architecture that made it unsustainable for scale?
What specific architectural changes were implemented in 'v2' to drastically improve diff line performance?
How did the GitHub engineering team achieve quantifiable improvements in JavaScript heap, DOM nodes, and INP metrics with v2?
What is Interaction to Next Paint (INP) and why is its improvement significant for GitHub's user experience?
Xəbərdar olun
Ən son AI xəbərlərini e-poçtunuza alın.
