Derleme performansını ayırma

Sorun bildirin Kaynağı göster

Bazel karmaşık bir yapıdır ve derleme sırasında birçok farklı şey yapar. Bunların bazıları derleme performansını etkileyebilir. Bu sayfada, bazı Bazel kavramlarının derleme performansı üzerindeki etkileri eşleştirilmektedir. Kapsamlı olmasa da metrikleri ayıklayarak derleme performansı sorunlarını nasıl belirleyeceğinize ve bunları düzeltmek için neler yapabileceğinize dair bazı örnekleri ekledik. Bu bilgiyle, performans regresyonlarını araştırırken bu kavramları uygulayabileceğinizi umuyoruz.

Temiz ve Artımlı derlemeler

Temiz bir derleme her şeyi sıfırdan oluşturur. Buna karşılık, artımlı bir derleme önceden tamamlanmış bazı çalışmaları yeniden kullanır.

Temiz ve artımlı derlemeleri ayrı ayrı incelemenizi öneririz. Özellikle de Bazel'ın önbelleklerinin durumuna bağlı olan metrikleri toplarken / toplarken (örneğin, istek boyutu metrikleri oluşturma). Ayrıca, iki farklı kullanıcı deneyimini temsil ederler. Sıfırdan temiz bir derleme başlatmaya kıyasla (sıfır önbellek nedeniyle daha uzun sürer) geliştiriciler kod tekrarladıkça çok daha sık gerçekleşir (genellikle önbellek zaten sıcak olduğundan bu daha hızlı gerçekleşir).

Derlemeleri sınıflandırmak için BEP'deki CumulativeMetrics.num_analyses alanını kullanabilirsiniz. num_analyses <= 1, temiz bir yapıdır. Aksi takdirde, muhtemelen derlemeyi artımlı bir derleme olarak geniş bir kategorize edebiliriz. Kullanıcı farklı flag'lere veya farklı hedeflere geçerek etkili bir derleme oluşturmaya neden olmuş olabilir. Artımlılığın daha titiz bir şekilde tanımlanması, muhtemelen buluşsal biçimde olmalıdır; örneğin, yüklenen paketlerin sayısına bakılması (PackageMetrics.packages_loaded).

Derleme performansı için proxy olarak belirleyici derleme metrikleri

Derleme performansını ölçmek, belirli metriklerin (örneğin, Bazel'ın CPU süresi veya uzak bir kümedeki sıra süreleri) belirleyici olmaması nedeniyle zor olabilir. Bu nedenle, Bazel'ın yaptığı çalışmaların miktarı için proxy olarak belirleyici metrikler kullanmak yararlı olabilir ve bu da performansını etkiler.

Derleme isteğinin boyutu, derleme performansını önemli ölçüde etkileyebilir. Daha büyük bir yapı, derleme grafiklerinin analiz edilmesi ve oluşturulmasında daha fazla çalışma yapıldığını gösterebilir. Derlemelerin organik büyümesi, daha fazla bağımlılık eklendikçe/oluşturulduğunda doğal olarak geliştirmeyle birlikte gerçekleşir. Bu nedenle karmaşıklık düzeyi arttıkça yapı oluşturmanın maliyeti de artar.

Bu sorunu çeşitli derleme aşamalarına ayırabilir ve her aşamada gerçekleştirilen çalışmalar için proxy metriği olarak aşağıdaki metrikleri kullanabiliriz:

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

    • Bu durum genellikle bağımlılık eklenmesinden ve geçişli kapanmayı yüklemekten kaynaklanır.
    • Yeni bağımlıların eklenebileceği yerleri bulmak için query / cquery aracını kullanın.
  2. TargetMetrics.targets_configured: Derlemede yapılandırılan hedef ve özellik sayısını temsil eder. Regresyon, yapılandırılmış hedef grafiğin oluşturulması ve geçişi için yapılan daha fazla çalışmayı temsil eder.

    • Bunun nedeni genellikle bağımlılık eklenmesi ve geçişli kapanmanın grafiğini oluşturmaktır.
    • Yeni bağımsız kaynakların eklenmiş olabileceği yerleri bulmak için cquery aracını kullanın.
  3. ActionSummary.actions_created: Derlemede oluşturulan işlemleri temsil eder. Regresyon ise işlem grafiğinin oluşturulmasında yapılan diğer çalışmaları temsil eder. Buna, çalıştırılmamış olabilecek kullanılmayan işlemler de dahildir.

  4. ActionSummary.actions_executed: Yapılan işlem sayısı. Regresyon doğrudan bu işlemlerin yürütülmesi için yapılan çalışmaları temsil eder.

    • BEP, en çok yürütülen işlem türlerini gösteren işlem istatistiklerini ActionDatayazır. Varsayılan olarak, en popüler 20 işlem türü toplanır ancak yürütülen tüm işlem türleri için bu verileri toplamak üzere --experimental_record_metrics_for_all_mnemonics türünü iletebilirsiniz.
    • Bu, ne tür işlemler yapıldığını (ayrıca) anlamanıza yardımcı olur.
  5. BuildGraphSummary.outputArtifactCount: Yürütülen işlemler tarafından oluşturulan yapıların sayısıdır.

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

Bu metriklerin tamamı yerel önbelleğin durumundan etkilendiği için bu metrikleri çıkardığınız derlemelerin temiz derlemeler olduğundan emin olmanız gerekir.

Bu metriklerden herhangi birindeki regresyonun, duvar süresi, işlem süresi ve bellek kullanımındaki regresyonlarla birlikte görülebildiğini gözlemledik.

Yerel kaynakların kullanımı

Bazel, yerel makinenizde çeşitli kaynaklar tüketir (hem derleme grafiğini analiz etmek hem de yürütmeyi çalıştırmak ve yerel işlemleri çalıştırmak için). Bu işlem, makinenizin derlemeyi yaparken gösterdiği performansı / stok durumunu ve diğer görevleri etkileyebilir.

Harcanan süre

Belki de gürültüye en açık olan metrikler (ve derlemeden derlemeye büyük ölçüde farklılık gösterebilir) zaman, özellikle de duvar süresi, işlem süresi ve sistem saatidir. Bu metrikleri temel alan bir karşılaştırma almak için bazel-bench'i kullanabilir ve yeterli sayıda --runs ile ölçümünüzün istatistiksel önemini artırabilirsiniz.

  • Duvar saati, geçen gerçek zamandır.

    • Yalnızca gerçek zamanlı düzenlemeler geri dönüyorsa JSON izleme profili toplamanızı ve farkları aramanızı öneririz. Aksi takdirde, diğer geri çekilen metrikleri, duvarın süresini etkilemiş olabilecekleri için araştırmak daha verimli olacaktır.
  • CPU süresi, kullanıcı kodunu yürüten CPU tarafından harcanan süredir.

    • CPU süresi iki proje kaydında geri düşerse bir Starlark CPU profili toplamanızı öneririz. CPU'nun yoğun olarak kullanıldığı işlerin çoğu burada yapıldığından, analizi analiz aşamasıyla sınırlamak için muhtemelen --nobuild kullanmanız gerekir.
  • Sistem süresi, CPU'nun çekirdekteki harcadığı süredir.

    • Sistem saati geri düşerse Bazel dosya sisteminizdeki dosyaları okuduğunda genellikle I/O ile ilişkili olur.

Sistem genelinde yük profili oluşturma

JSON iz profili oluşturucu, Bazel 6.0'da kullanılan --experimental_collect_load_average_in_profiler işaretini kullanarak çağrı sırasındaki 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ındaki yüksek yük, Bazel'ın makinenize paralel olarak çok fazla yerel işlem planladığının göstergesi olabilir. Özellikle kapsayıcı ortamlarında (en azından #16512 birleşene kadar) --local_cpu_resources ve --local_ram_resources özelliklerini ayarlamayı deneyebilirsiniz.

Bazel bellek kullanımını izleme

Bazel'ın bellek kullanımını alabileceğiniz iki ana 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 bank bu metrik için de karşılaştırmalar sağlar.
    • Ayrıca peak-heap-size, max-heap-size, used-heap-size ve committed-heap-size mevcuttur (belgelere bakın), ancak alaka düzeyi daha düşüktür.
  • BEP MemoryMetrics.peak_post_gc_heap_size: GC sonrası bayt cinsinden en yüksek JVM yığın boyutunun boyutu (tam GC'yi zorunlu kılmaya çalışan --memory_profile ayarı gerekir).

Hafıza kullanımındaki regresyon genellikle istek boyutu oluşturma metriklerindeki bir regresyondan kaynaklanır. Bu durum genellikle bağımlıların eklenmesi veya kural uygulamasında yapılan bir değişiklikten kaynaklanır.

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

Kalıcı çalışanların bellek profili oluşturma

Kalıcı çalışanlar derlemeleri önemli ölçüde hızlandırmaya yardımcı olabilir (özellikle yorumlanan diller için) bellek ayak izi sorunlu olabilir. Bazel, özellikle çalışanlarına ne kadar bellek kullandığını (hafıza bazında) WorkerMetrics.WorkerStats.worker_memory_in_kb alanında belirtir.

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

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

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

--worker_max_instances değerini (varsayılan 4) düşürmek, 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 hassas düzenlemeler daha az zorunlu olacak.

Uzak derlemeler için ağ trafiğini izleme

Uzaktan yürütme sırasında Bazel, işlemlerin yürütülmesi sonucunda oluşturulan yapıları indirir. Bu nedenle, ağ bant genişliğiniz derlemenizin performansını etkileyebilir.

Derlemeleriniz için uzaktan yürütme özelliğini kullanıyorsanız BEP'den NetworkMetrics.SystemNetworkStats protosunu kullanarak çağrı sırasında ağ trafiğini izlemeyi düşünebilirsiniz (--experimental_collect_system_network_usage öğesinin iletilmesi gerekir).

Buna ek olarak, JSON izleme profilleri, --experimental_collect_system_network_usage flag'ini (Bazel 6.0'daki yeni) geçirerek sistem genelinde ağ kullanımını görüntülemenize olanak tanır.

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

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

Uzaktan yürütme kullanırken yüksek düzeyde ancak yine de düz bir ağ kullanımı, derlemenizdeki darboğazın ağ olduğunu gösterebilir. Henüz kullanmıyorsanız --remote_download_minimal'i geçerek Derlemeyi Bayt olmadan etkinleştirme seçeneğini değerlendirin. 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 bir disk önbelleği yapılandırmaktır.