· kaynak GitHub Blog
GitHub, Copilot uygulamasının diff görünümünü milyonluk satırlı pull request'leri render edebilecek şekilde yeniden inşa etti
GitHub, Copilot uygulamasının yeniden inşa edilen diff yüzeyinin; düzeni iki bağımsız geometriye bölerek, 2.200 dosyalık, bir milyondan fazla değiştirilmiş satır ve 400 satır içi yorum içeren bir pull request'i açabildiğini belirtiyor.

GitHub Blog'a göre GitHub, Copilot uygulaması içindeki diff yüzeyini çok büyük pull request'lerin incelenirken hızlı ve akıcı kalması için yeniden inşa etti. Bunu tetikleyen gerçek bir durum var: geniş kapsamlı refactor'lar ve migration'lar çoğu zaman stacked pull request'lere bölünemiyor ve bu da incelenmesi büyüyüp duran tek devasa bir değişiklik bırakıyor. Yeni görünümü stres testinden geçirmek için ekip bulabildikleri en büyük pull request'i açtı: 2.200 dosyaya dokunan, bir milyondan fazla değiştirilmiş satır ve 400'ün üzerinde satır içi inceleme yorumu içeren açık kaynak bir değişiklik.
Yorumlarla ilgili sorun
Yazı, hızlı diff render'ının iyi anlaşılmış bir alan olduğu konusunda açık sözlü: satırları virtualize et, yalnızca ekrana yakın olanları mount et ve kullanıcı kaydırdıkça DOM elemanlarını geri dönüştür. Her satır bilinen bir yazı tipi boyutunda bir kod satırı olduğu için, scrollbar'ı ve satır konumlarını yönlendiren yükseklik tablosu tamamen baştan hesaplanabilir ve asla değişmez. GitHub buna "paint öncesi tüm yükseklikler bilinir" sözü adını veriyor ve yüzeyin kod tarafı bu ilkeye göre kurulmuş: imperative bir geri dönüştürülen satır renderer'ı, typed-array offset hesaplamaları, backend'den structure-first akan diff dokümanları ve imperative bir scroll-to-row API'si kullanılıyor.
Satır içi inceleme yorumları bu sözü bozuyor. Bir yorumun ne kadar uzun olduğunu onu render edene kadar bilemezsiniz: markdown farklı genişliklerde farklı sarılır, bölümler açılıp kapanır, yanıt yazma alanı yazarken büyür, suggested-change diff'leri ve tepkiler boyut değiştirir ve görseller yüklenmeyi bitirdiğinde düzeni kaydırır. Yorum başına, bir tahmin ediciyle boyutlandırılan sabit yükseklikli bir alan ayırmak ölçek altında başarısız oluyor. Çoğu yorumda fazla boşluk kalıyor, pahalı olanlar kesiliyor veya iç içe bir scrollbar büyütüyor ve ölçülen bir yüksekliği paylaşılan offset tablosuna geri yazmak, kullanıcı zaten kaydırırken aşağıdaki her şeyi hareket ettirerek büyük bir kaydırma sıçraması üretiyor.
Bir yerine iki geometri
Yazıya göre sorunu çözülebilir kılan fikir, tek bir geometriyi her iki içerik türüne de hizmet etmeye zorlamayı reddetmekti. Dokümanın toplam yüksekliği artık deterministik kod yüksekliği, dinamik blok yüksekliklerinin toplamı ve scroll padding olarak bölünüyor. Kod geometrisi kesin kalıyor ve bir yorum yeniden boyutlandığında asla yeniden inşa edilmiyor.
İnceleme thread'lerini, taslakları ve yanıt yazma alanlarını kapsayan dinamik bloklar, bir piksel koordinatına değil dosya, satır ve tarafa sabitlenmiş kararlı anahtarlarla tanımlanıyor, böylece bir reflow onların izini kaybettiremiyor. Her blok, yüksekliğini değiştirebilecek her şeyin bir parmak izini ve son ölçüldüğü genişlik kovasını taşıyor, böylece sıradan bir pencere yeniden boyutlandırması dokümandaki her ölçümü geçersiz kılmıyor. Bir blokun efektif yüksekliği ölçülenden cache'lenene, oradan tahmin edilene düşüyor ve blok sayısı satır değil yorum sayısıyla ölçekleniyor; ekip, ilk paint hepsini aynı anda mount etmediği veya ölçmediği sürece birkaç bin blokta bunun sorun olmadığını düşünüyor.
İlk seferde yanlış yaptıkları scheduler
GitHub'ın ilk ölçüm tasarımı blok başına bir ResizeObserver kullanıyordu ve ekip performans sağlamlaştırma sırasında bunu reddetti. İzlediği elemanın layout'una yükseklikleri geri yazan bir observer kendini yeniden tetikleyebiliyor ve maliyet mount edilen her blokla büyüyor; bu tam olarak büyük virtualize edilmiş yüzeylerin kaçınması gereken geri besleme döngüsü.
Bunun yerine shipped edilen şey, idle ve scroll'a bağlı tek bir ölçüm geçişi. Görünür aralık oturduğunda bir kez çalışıyor, asla scroll frame'i başına bir kez çalışmıyor ve bir scroll sürerken tamamen bekliyor, çünkü scroll ortasında bir reflow kaçınılan takılmanın ta kendisi. Yalnızca viewport'a kabaca 2.400 piksel uzaklıktaki bloklar aday oluyor ve iş viewport'a değil dokümana oranlı kalıyor.
Yazı ayrıca bu yeniden inşadaki diğer iki zor problemi de adlandırıyor: yüzeyi besleyen veri pipeline'ı, duraksarsa veya yaptığı işi çöpe atarsa işe yaramaz; ve bug'ları bulmanın zorluğu. Bu sorunlar yalnızca yük altında, belirli bir motor üzerinde, belirli bir scroll konumunda ortaya çıkıyor; bu yüzden ekip sağlıklının ne demek olduğunu tanımladı, yüzeyi bu tanıma göre instrumente etti ve değiştir-ölç-iyileştir döngüsünü gözetimsiz çalıştırdı.
Neden önemli
Bazı değişiklikler gerçekten küçük stacked pull request'ler olarak merge edilemez ve inceleme aracı onlarda kötüleşirse, ekipler daha zayıf incelemeye veya daha riskli merge'lere itilir. GitHub'ın ötesinde, yazı karma içerikli virtualize arayüzler yapan herkes için bir şablon niteliğinde: boyutunu baştan bildiğiniz içerik için tek bir layout sistemi tutun, boyutunu yalnızca render anında öğrendiğiniz içeriği izole edin, ölçüm işini viewport'a bağlayın ve sentetik listeler yerine gerçekçi uç durumlarla doğrulayın. Milyon satırlık test vakası bunun özü, çünkü inceleme araçlarındaki performans yalnızca incelemenin gerçekten acıttığı boyutlarda önemlidir.
- #github
- #copilot
- #code-review
- #performance
- #virtualization