Derleme performansını ayırma

Sorun bildirin Kaynağı göster

Bazel karmaşıktır ve derleme işlemi boyunca birçok farklı işlem gerçekleştirir. Bu işlemlerden bazıları derleme performansını etkileyebilir. Bu sayfa, bu Bazel kavramlarından bazılarını derleme performansı üzerindeki etkileriyle eşlemeye çalışmaktadır. Kapsamlı olmamakla birlikte, metrikleri çıkararak derleme performansı sorunlarının nasıl tespit edileceği ve bunları düzeltmek için neler yapabileceğinize dair bazı örnekler ekledik. Bu sayede, performans regresyonlarını araştırırken bu kavramları uygulayabileceğinizi umuyoruz.

Temiz ve Artımlı derlemeler

Temiz derleme, her şeyi sıfırdan derlerken artımlı derlemeler, tamamlanmış bazı çalışmaları yeniden kullanır.

Özellikle Bazel'ın önbelleklerinin durumuna bağlı olan metrikleri (örneğin, derleme isteği boyutu metrikleri) toplarken / toplarken temiz ve artımlı derlemelere ayrı ayrı bakmanızı öneririz. Bunlar aynı zamanda iki farklı kullanıcı deneyimini temsil eder. Sıfırdan (sıfır önbellek nedeniyle daha uzun sürer) temiz bir derleme başlatmaya kıyasla, artımlı derlemeler geliştiriciler kod üzerinde yineleme yaptıkça çok daha sık gerçekleşir (önbellek genellikle zaten hazır olduğundan daha hızlıdır).

Derlemeleri sınıflandırmak için BEP'deki CumulativeMetrics.num_analyses alanını kullanabilirsiniz. num_analyses <= 1 ise temiz bir derlemeyse; aksi takdirde, genel bir şekilde artımlı derleme olarak kategorize edebiliriz. Kullanıcı, farklı flag'lere veya farklı hedeflere geçerek etkili şekilde temiz bir derleme oluşturabilir. Artımlılığın daha ayrıntılı bir şekilde tanımlanması, muhtemelen bulgusal bir yöntemle ortaya çıkacaktır (ör. yüklenen paket sayısına bakmak (PackageMetrics.packages_loaded).

Derleme performansı için proxy olarak belirleyici derleme metrikleri

Derleme performansını ölçmek, belirli metriklerin deterministik olmayan yapısı nedeniyle zor olabilir (örneğin, Bazel'in CPU süresi veya uzak bir kümedeki sıra süreleri). Bu nedenle, Bazel'in yaptığı iş miktarını referans olarak göstermek için deterministik metrikleri kullanmak yararlı olabilir, bu da Bazel'in performansını etkiler.

Derleme isteğinin boyutu, derleme performansını önemli ölçüde etkileyebilir. Daha büyük bir yapı, yapı grafiklerinin analiz edilmesi ve oluşturulmasında daha fazla iş yapılmasını sağlayabilir. Daha fazla bağımlılık eklendikçe/oluşturuldıkça derlemelerin organik büyümesi doğal olarak gelişir. Bu da karmaşıklık olarak artar ve derleme maliyetleri artar.

Bu problemi çeşitli derleme aşamalarına ayırabilir ve her aşamada yapılan işler için ara metrikler olarak aşağıdaki metrikleri kullanabiliriz:

  1. PackageMetrics.packages_loaded: Başarıyla yüklenen paketlerin sayısı. Buradaki regresyon, yükleme aşamasında her ek BUILD dosyasını okuyup ayrıştırmak için yapılması gereken daha fazla işi temsil eder.

    • Bunun nedeni genellikle bağımlılıkların eklenmesi ve bunların geçişli kapanışlarını yüklemek zorunda olmasıdır.
    • Yeni bağımlılıkların eklenmiş olabileceği yerleri bulmak için query / cquery komutunu kullanın.
  2. TargetMetrics.targets_configured: Derlemede yapılandırılan hedef ve boyutların sayısını temsil eder. Regresyon, yapılandırılmış hedef grafiğin oluşturulurken ve bu grafikte gezinmede daha fazla iş yapılması anlamına gelir.

    • Bunun nedeni genellikle bağımlılıkların eklenmesi ve bunların geçişli kapanış grafiğini oluşturmak zorunda olmasıdır.
    • Yeni bağımlılıkların nereye eklenebileceğini bulmak için cquery komutunu kullanın.
  3. ActionSummary.actions_created: Derlemede oluşturulan işlemleri temsil eder. Regresyon ise eylem grafiğinin oluşturulmasında daha fazla çalışmayı temsil eder. Bu işlemin, yürütülmemiş olabilecek kullanılmayan işlemleri de içerdiğini unutmayın.

  4. ActionSummary.actions_executed: Yürütülen işlemlerin sayısıdır. Regresyon, doğrudan bu işlemlerin yürütülmesinde daha fazla işin yapıldığını gösterir.

    • BEP, en çok yürütülen işlem türlerini gösteren işlem istatistiklerini ActionData yazar. Varsayılan olarak, en iyi 20 işlem türünü toplar, ancak yürütülen tüm işlem türleri için bu verileri toplamak istiyorsanız --experimental_record_metrics_for_all_mnemonics'ı iletebilirsiniz.
    • Bu, ne tür işlemlerin gerçekleştirildiğini anlamanıza yardımcı olur (ayrıca).
  5. BuildGraphSummary.outputArtifactCount: Yürütülen işlemler tarafından oluşturulan yapıların sayısı.

    • Yürütülen işlemlerin sayısı artmadıysa muhtemelen bir kural uygulaması değişmiştir.

Bu metriklerin tümü yerel önbelleğin durumundan etkilenir. Bu nedenle, bu metrikleri çıkardığınız derlemelerin temiz derlemeler olduğundan emin olmanız gerekir.

Bu metriklerdeki regresyona duvar süresi, CPU süresi ve bellek kullanımındaki regresyonlar da dahildir.

Yerel kaynakların kullanımı

Bazel, yerel makinenizde çeşitli kaynakları tüketir (hem derleme grafiğini analiz etmek hem de yürütmeyi yürütmek ve yerel işlemleri çalıştırmak için) bu durum, derleme ve diğer görevlerin gerçekleştirilmesi sırasında makinenizin performansını / kullanılabilirliğini etkileyebilir.

Harcanan süre

Belki de gürültüye en çok açık olan (ve derlemeden yapıya büyük farklılıklar gösterebilen) metrikler, özellikle de duvar süresi, CPU süresi ve sistem süresidir. Bu metrikler için karşılaştırma elde etmek üzere bazel-bench yöntemini kullanabilirsiniz. Yeterli sayıda --runs olduğunda ölçümünüzün istatistiksel anlamını artırabilirsiniz.

  • Duvar saati, gerçek dünyada geçen süredir.

    • Yalnızca duvar süresi geri dönüyorsa bir JSON iz profili toplamanızı ve farklılıkları aramanızı öneririz. Aksi takdirde, regresyon süresini etkileyebileceğinden diğer regresyon metriklerinin incelenmesi daha verimli olacaktır.
  • CPU süresi, CPU'nun kullanıcı kodunu yürütmesi için harcanan süredir.

    • İki proje kaydetme işleminde CPU süresi geriliyorsa Starlark CPU profili toplamanızı öneririz. CPU yoğun işlerin büyük bir kısmı bu aşamada yapıldığından derlemeyi analiz aşamasıyla kısıtlamak için muhtemelen --nobuild yöntemini de kullanmanız gerekir.
  • Sistem süresi, çekirdekte CPU tarafından harcanan süredir.

    • Sistem saati geride kalırsa Bazel, dosya sisteminizden dosyaları okuduğunda bu çoğunlukla G/Ç ile ilişkilidir.

Sistem genelinde yük profili oluşturma

JSON iz profil aracı, Bazel 6.0'da kullanıma sunulan --experimental_collect_load_average_in_profiler işaretini kullanarak çağrı sırasında sistem yükü ortalamasını toplar.

Sistem yükü ortalamasını içeren profil

Şekil 1. Sistem yükü ortalamasını içeren profil.

Bazel çağrısı sırasında yüksek bir yük, Bazel'in makineniz için paralel olarak çok fazla yerel işlem programladığını gösterebilir. Özellikle kapsayıcı ortamlarında (en az #16512 birleştirilinceye kadar) --local_cpu_resources ve --local_ram_resources düzenlemelerini inceleyebilirsiniz.

Bazel bellek kullanımını izleme

Bazel'ın bellek kullanımını almak için iki ana kaynak vardır: Bazel info ve BEP.

  • bazel info used-heap-size-after-gc: System.gc() çağrısından sonra kullanılan bellek miktarı (bayt cinsinden).

    • Bazel karşılaştırması, bu metrik için de karşılaştırmalar sağlar.
    • Bunlara ek olarak, peak-heap-size, max-heap-size, used-heap-size ve committed-heap-size de vardır (belgelere bakın) ancak bunların alaka düzeyi daha düşüktür.
  • BEP'nin MemoryMetrics.peak_post_gc_heap_size: GC sonrası en yüksek JVM yığın boyutunun bayt cinsinden boyutu (tam GC'yi zorunlu kılmaya çalışan --memory_profile ayarlanması gerekir).

Bellek kullanımında regresyon, genellikle derleme isteği boyutu metriklerindeki regresyondan kaynaklanır. Bu da genellikle bağımlılıkların eklenmesi veya kural uygulamasındaki bir değişiklikten kaynaklanır.

Bazel'ın bellek ayak izini daha ayrıntılı bir şekilde analiz etmek üzere kurallar için yerleşik bellek profil oluşturucuyu kullanmanızı öneririz.

Kalıcı çalışanların bellek profilini çıkarma

Kalıcı çalışanlar, derlemelerin hızlandırılmasına yardımcı olabilir (özellikle yorumlanan diller için) ancak bellek ayak izi sorun yaratabilir. Bazel, çalışanları hakkında metrikler toplar. Özellikle de WorkerMetrics.WorkerStats.worker_memory_in_kb alanı, çalışanların ne kadar bellek kullandığını gösterir.

JSON iz profili aracı, çağrı sırasında --experimental_collect_system_network_usage işaretini (Bazel 6.0'da yeni olan) ileterek kalıcı çalışan bellek kullanımını da toplar.

Çalışanların bellek kullanımını içeren profil

Şekil 2. Çalışanların bellek kullanımını içeren profil.

--worker_max_instances değerini (varsayılan 4) düşürmek, kalıcı çalışanların kullandığı bellek miktarını azaltmaya yardımcı olabilir. Bazel'ın kaynak yöneticisi ve planlayıcısını daha akıllı hale getirmek için aktif olarak çalışıyoruz. Böylece, gelecekte bu tür ince ayarlar daha az ihtiyaç duyabilecek.

Uzaktan derlemeler için ağ trafiğini izleme

Uzaktan yürütmede Bazel, yürütülen işlemlerin sonucu olarak oluşturulan yapıları indirir. Bu nedenle, ağınızın bant genişliği derlemenizin performansını etkileyebilir.

Derlemeleriniz için uzaktan yürütme özelliğini kullanıyorsanız BEP'den NetworkMetrics.SystemNetworkStats protokolünü kullanarak çağrı sırasında ağ trafiğini izleyebilirsiniz (--experimental_collect_system_network_usage iletilmelidir).

Ayrıca JSON izleme profilleri, --experimental_collect_system_network_usage işaretini (Bazel 6.0'da yeni olan) ileterek derleme boyunca sistem genelindeki ağ kullanımını görüntülemenize olanak tanır.

Sistem genelinde ağ kullanımını içeren profil

Şekil 3. Sistem genelinde ağ kullanımını içeren profil.

Uzaktan yürütme kullanılırken yüksek ancak oldukça sabit ağ kullanımı, ağın derlemenizdeki performans sorunu olduğunu gösterebilir. Henüz kullanmıyorsanız Bayt olmadan derleme özelliğini --remote_download_minimal ileterek etkinleştirmeyi düşünebilirsiniz. Bu işlem, gereksiz ara yapıların indirilmesini önleyerek derlemelerinizi hızlandırır.

Diğer bir seçenek de indirme bant genişliğinden tasarruf etmek için yerel disk önbelleği yapılandırmaktır.