Derleme performansını ayırma

Sorun bildirme Kaynağı görüntüleme Nightly · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Bazel karmaşıktır ve derleme sırasında birçok farklı işlem yapar. Bunlardan bazıları derleme performansını etkileyebilir. Bu sayfada, bu Bazel kavramlarından bazılarının derleme performansı üzerindeki etkileriyle eşleştirilmesi amaçlanmıştı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, derleme performansı gerilemelerini incelerken bu kavramları uygulayabileceğinizi umuyoruz.

Temiz ve artımlı derlemeler

Temiz derleme, her şeyi sıfırdan derleyen bir derlemedir. Artımlı derleme ise daha önce tamamlanmış bazı çalışmaları yeniden kullanır.

Özellikle Bazel'in önbelleklerinin durumuna bağlı metrikleri (ör. derleme isteği boyutu metrikleri) toplayıp topladığınızda temiz ve artımlı derlemeleri ayrı ayrı incelemenizi öneririz. Ayrıca bu iki farklı kullanıcı deneyimini temsil eder. Temiz bir derlemeyi sıfırdan başlatmaya kıyasla (soğuk önbelleğe bağlı olarak daha uzun sürer), geliştiriciler kod üzerinde iterasyon yaparken artımlı derlemeler çok daha sık gerçekleşir (önbellek genellikle zaten sıcak olduğundan genellikle 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 derlemedir. Aksi takdirde, genel olarak artımlı bir derleme olarak sınıflandırabiliriz. Kullanıcı, etkili bir şekilde temiz bir derlemeye neden olacak şekilde farklı işaretlere veya farklı hedeflere geçmiş olabilir. 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ı üzerinde önemli bir etkiye sahip olabilir. Daha büyük bir derleme, derleme grafiklerinin analiz edilmesi ve oluşturulması için daha fazla çalışma gerektirebilir. Geliştirme sürecinde daha fazla bağımlılık eklendikçe/oluşturuldıkça derlemelerin organik olarak büyümesi doğaldır. Bu nedenle, derlemelerin karmaşıklığı artar ve derleme maliyeti yükselir.

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 gerileme, yükleme aşamasında her ek BUILD dosyasını okumak ve ayrıştırmak için yapılması gereken daha fazla çalışmayı temsil eder.

    • Bu durum genellikle bağımlılıkların eklenmesi ve geçişli kapatmalarının yüklenmesi gerektiğinden kaynaklanır.
    • Yeni bağımlılıkların eklenmiş olabileceği yerleri bulmak için query / cquery'yi kullanın.
  2. TargetMetrics.targets_configured: Derlemede yapılandırılan hedeflerin ve özelliklerin sayısını temsil eder. Gerileme, yapılandırılmış hedef grafiği oluşturma ve bu grafikte gezinme konusunda daha fazla çalışmayı temsil eder.

    • 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 ve gerileme, işlem grafiğinin oluşturulmasında daha fazla çalışma olduğunu gösterir. Bu süreye, yürütülmemiş olabilecek kullanılmayan işlemler de dahildir.

  4. ActionSummary.actions_executed: Yapılan işlem sayısı. Düşüş, bu işlemlerin uygulanmasında daha fazla çalışma 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 popüler 20 işlem türünü toplar ancak yürütülen tüm işlem türleri için bu verileri toplamak üzere --experimental_record_metrics_for_all_mnemonics parametresini 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ı.

    • Yapılan işlem sayısı artmadıysa büyük olasılıkla bir kural uygulaması değiştirilmiş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 metriklerden herhangi birinde görülen gerilemelerin, gerçek zaman, CPU süresi ve bellek kullanımında da gerilemelere neden olabileceğini fark ettik.

Yerel kaynakların kullanımı

Bazel, yerel makinenizde çeşitli kaynakları tüketir (hem derleme grafiğini analiz etmek ve yürütmeyi yönlendirmek hem de yerel işlemleri çalıştırmak için). Bu durum, makinenizin derlemeyi ve diğer görevleri gerçekleştirmedeki performansını / kullanılabilirliğini etkileyebilir.

Harcanan süre

Gürültüye en açık metrik (ve derlemeden derlemeye büyük ölçüde değişiklik gösterebilir) zamandır; özellikle de gerçek zaman, CPU zamanı ve sistem zamanı. Bu metrikler için karşılaştırma yapmak üzere bazel-bench'i kullanabilir ve yeterli sayıda --runs ile ölçümünüzün istatistiksel anlamlılığını artırabilirsiniz.

  • Toplam süre, geçen gerçek zamandır.

    • Yalnızca gerçek zaman geri gidiyorsa JSON izleme profili toplayıp farklılıkları incelemenizi öneririz. Aksi takdirde, duvar süresini etkileyebilecekleri için geriye dönük diğer metrikleri incelemek daha verimli olabilir.
  • CPU süresi, CPU'nun kullanıcı kodunu yürütmek için harcadığı süredir.

    • CPU süresi iki proje taahhütünde geriye gidiyorsa bir Starlark CPU profili toplamanızı öneririz. CPU'ya yoğun iş yükünün çoğunun analiz aşamasında gerçekleştiği için derlemeyi analiz aşamasına kısıtlamak için --nobuild'ü de kullanmanız gerekir.
  • Sistem süresi, CPU'nun çekirdekte geçirdiği süredir.

    • Sistem zamanı geriye gidiyorsa bu durum genellikle Bazel'in dosya sisteminizdeki dosyaları okuduğu I/O ile ilişkilidir.

Sistem genelinde yük profilleme

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 yük, Bazel'in makineniz için paralel olarak çok fazla yerel işlem planladığının bir göstergesi olabilir. Ö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'in bellek kullanımını öğrenmek için iki temel kaynak vardır: Bazel info ve BEP.

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

    • Bazel bench 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 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'in bellek kullanımını daha ayrıntılı bir düzeyde analiz etmek için kurallarda yerleşik bellek profilleyiciyi kullanmanızı öneririz.

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

Kalıcı çalışanlar, derlemeleri önemli ölçüde hızlandırmaya yardımcı olabilir (özellikle yorumlanan diller için) ancak bellek ayak izi sorunlu olabilir. Bazel, çalışanlarıyla ilgili metrikler toplar. Özellikle WorkerMetrics.WorkerStats.worker_memory_in_kb alanı, çalışanların ne kadar bellek kullandığını (hatırlatıcıya göre) gösterir.

JSON izleme profilleyicisi, --experimental_collect_system_network_usage işaretini (Bazel 6.0'da yeni) ileterek de çağrı sırasında kalıcı çalışan bellek kullanımını 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 düşürmek (varsayılan 4) kalıcı çalışanlar tarafından kullanılan bellek miktarını azaltmaya yardımcı olabilir. Bazel'ın kaynak yöneticisini 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.

Uzak derlemeler için ağ trafiğini izleme

Bazel, uzaktan çalıştırma sırasında işlemleri yürütme sonucunda 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 genelindeki ağ kullanımını içeren profil.

Uzak yürütme kullanılırken yüksek ancak oldukça düz bir ağ kullanımı, ağınızın derlemenizdeki darboğaz olduğunu gösterebilir. Henüz kullanmıyorsanız --remote_download_minimal parametresini ileterek Bayt olmadan derlemeyi etkinleştirebilirsiniz. Bu, 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.