Derleme performansını ayırma

Sorun bildirme Kaynağı görüntüleme Nightly · 8.0 . 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, Bazel'deki bazı kavramların derleme performansı üzerindeki etkileri gösterilmeye çalışılmaktadır. Kapsamlı olmasa da metrikleri ayıklayarak derleme performansı sorunlarını nasıl tespit edebileceğinize 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 (bu işlem, soğuk önbelleğe bağlı olarak daha uzun sürer), geliştiriciler kodda iterasyon yaparken artımlı derlemeler çok daha sık gerçekleşir (önbelleğe genellikle zaten sıcak olduğu için 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çiş yapmış olabilir. Artımlılığın daha titiz bir tanımı için muhtemelen bir sezgisel bilgi biçimi (ör. yüklenen paketlerin sayısına bakma (PackageMetrics.packages_loaded)) kullanılmalıdır.

Derleme performansının proxy'si olarak belirleyici derleme metrikleri

Belirli metriklerin (ör. Bazel'in uzak bir kümedeki CPU süresi veya sıra süreleri) kesin olmayan yapısı nedeniyle derleme performansını ölçmek zor olabilir. Bu nedenle, Bazel tarafından yapılan iş miktarının ve dolayısıyla performansının bir temsilcisi olarak deterministik metrikleri kullanmak yararlı olabilir.

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, derlemeler daha karmaşık hale gelir ve derlemenin maliyeti artar.

Bu sorunu çeşitli derleme aşamalarına ayırabilir ve her aşamada yapılan çalışmalar için proxy metrikleri 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 hedef 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.

    • Bu durum genellikle bağımlılıkların eklenmesi ve geçişli kapatmalarının grafiğinin oluşturulması gerektiğinden kaynaklanır.
    • Yeni bağımlılıkların nerede eklenmiş olabileceğini bulmak için cquery'yi 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 yapılmasını 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 sayede, ne tür işlemlerin (ek olarak) gerçekleştirildiğini anlayabilirsiniz.
  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 ayıklayacağınız derlemelerin temiz derlemeler olduğundan emin olmanız gerekir.

Bu metriklerden herhangi birinde gerileme yaşanmasının, gerçek zaman, CPU süresi ve bellek kullanımında da gerilemeyle birlikte 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 zamanı, 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

Bazel 6.0'da kullanıma sunulan --experimental_collect_load_average_in_profiler işaretçisini kullanan JSON izleme profilleyicisi, ç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ından #16512 birleştirilene kadar) --local_cpu_resources ve --local_ram_resources değerlerini ayarlayabilirsiniz.

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.
    • Ayrıca peak-heap-size, max-heap-size, used-heap-size ve committed-heap-size (dokümanlara bakın) vardır ancak bunlar daha az alakalı.
  • BEP'nin MemoryMetrics.peak_post_gc_heap_size: GC'den sonraki en yüksek JVM yığın boyutunun bayt cinsinden değeri (tam GC'yi zorlamaya çalışan --memory_profile ayarını gerektirir).

Bellek kullanımındaki gerileme genellikle derleme isteği boyutu metriklerindeki gerilemenin bir sonucudur. Bu gerileme genellikle bağımlılıkların eklenmesi veya kural uygulamasında yapılan 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'ta 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. Gelecekte bu tür hassas ayarların daha az yapılması için Bazel'in kaynak yöneticisini ve planlayıcısını daha akıllı hâle getirmek için yoğun şekilde çalışıyoruz.

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ğ bant genişliğiniz derlemenizin performansını etkileyebilir.

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

Ayrıca JSON izleme profilleri, --experimental_collect_system_network_usage işaretini ileterek (Bazel 6.0'da yeni) derleme sırasında 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.

İndirme bant genişliğinden tasarruf etmek için yerel bir disk önbelleği yapılandırabilirsiniz.