Derleme performansını ayırma

Sorun bildir Kaynağı göster

Bazel karmaşık bir yapıdır ve derleme süresince 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ı oluşturma performansı üzerindeki etkileriyle eşleştirmeye çalışır. Derleme performansı sorunlarının metrikleri çıkararak nasıl tespit edileceği ve bunları düzeltmek için neler yapabileceğinizle ilgili örnekler ekledik. Böylece performans regresyonlarını derleme konusunu araştırırken bu kavramları uygulayabileceğinizi umuyoruz.

Temiz ve Artımlı derlemeler

Temiz derleme, her şeyi sıfırdan inşa eden derlemedir. Artımlı derleme ise tamamlanmış çalışmaların bazılarını yeniden kullanır.

Temiz ve artımlı derlemeleri ayrı olarak incelemenizi öneririz. Bu durum özellikle Bazel önbelleklerinin durumuna bağlı metrikleri (örneğin, istek boyutu metrikleri oluşturma) topluyor / toplarken kullanılıyor. Ayrıca iki farklı kullanıcı deneyimini temsil eder. Temiz bir derlemeyi sıfırdan (soğuk önbellek nedeniyle daha uzun sürer) başlatmaya kıyasla, artımlı derlemeler, geliştiriciler kod üzerinde yineledikçe ç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, bunu geniş ölçüde artımlı bir derleme olarak sınıflandırabiliriz. Kullanıcı farklı bayraklara veya farklı hedeflere geçerek etkili bir şekilde temiz bir derleme elde edebilir. Artımlılığın daha ayrıntılı bir tanımı muhtemelen buluşsal bir biçimde yapılmalıdır (örneğin, yüklenen paketlerin sayısına (PackageMetrics.packages_loaded) bakmak).

Derleme performansının göstergesi olarak belirleyici derleme metrikleri

Belirli metriklerin (örneğin, Bazel'in CPU süresi veya uzak bir kümedeki sıra süreleri) belirleyici olmayan yapısı nedeniyle derleme performansını ölçmek zor olabilir. Bu nedenle, Bazel tarafından yapılan iş miktarının göstergesi olarak deterministik metriklerin kullanılması 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 çalışma anlamına gelebilir. Daha fazla bağımlılık eklendiğinde/oluşturulduğunda ve bunun sonucunda karmaşıklık büyüdüğünde ve derlemenin maliyeti daha yüksek olduğundan derlemelerin organik büyümesi de geliştirmeyle doğal bir şekilde gerçekleşir.

Bu sorunu çeşitli oluşturma aşamalarına ayırabilir ve aşağıdaki metrikleri her bir aşamada yapılan işler için temsili metrikler olarak kullanabiliriz:

  1. PackageMetrics.packages_loaded: Başarıyla yüklenen paketlerin sayısı. Buradaki bir regresyon, yükleme aşamasında her ek DERLEME 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ıkların eklenmesi ve bunların geçişli kapanışını yüklemek zorunda kalmasından kaynaklanır.
    • Yeni bağımlılıkların nereye eklenmiş olabileceğini bulmak için query / cquery komutunu kullanın.
  2. TargetMetrics.targets_configured: Derlemede yapılandırılan hedeflerin ve boyutların sayısını temsil eder. Regresyon, yapılandırılmış hedef grafiğin oluşturulması ve bu grafikler arasında geçiş yapılması için daha fazla çalışmayı temsil eder.

    • Bu durum, genellikle bağımlılıkların eklenmesi ve bunların geçişli kapanma grafiğini oluşturmak zorunda kalmasından kaynaklanır.
    • Yeni bağımlılıkların nereye eklenmiş olabileceğini bulmak için cquery kullanın.
  3. ActionSummary.actions_created: Derlemede oluşturulan işlemleri temsil eder; regresyon ise işlem grafiğinin oluşturulmasında daha fazla iş yapılmasını temsil eder. Bunun, yürütülmemiş olabilecek kullanılmayan işlemleri de içerdiğini unutmayın.

  4. ActionSummary.actions_executed: Yürütülen işlem sayısıdır. regresyon, bu işlemlerin yürütülmesinde gerçekleştirilen daha fazla işi doğrudan temsil eder.

    • BEP, en çok yürütülen işlem türlerini gösteren işlem istatistiklerini ActionData yazar. Varsayılan olarak, en önemli 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 bilgisini iletebilirsiniz.
    • Bu, ne tür işlemlerin gerçekleştirildiğini (ek olarak) anlamanıza yardımcı olur.
  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 bir kural uygulaması değiştirilmiş olabilir.

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 birindeki regresyona duvar süresi, CPU süresi ve bellek kullanımındaki regresyonlar eşlik edebilir.

Yerel kaynakların kullanımı

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

Harcanan süre

Belki de parazitten en çok etkilenen (ve derlemeden derlemeye kadar büyük farklılıklar gösterebilen) metrikler zamandır. Özellikle de duvar süresi, CPU süresi ve sistem süresidir. Bu metrikler için bir karşılaştırma elde etmek üzere bazel-bench kullanabilir ve yeterli sayıda --runs ile ölçümünüzün istatistiksel anlamını artırabilirsiniz.

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

    • Yalnızca gerçek zamanlı regresyonlar varsa bir JSON iz profili toplayıp farklılıkları aramanızı öneririz. Aksi takdirde, duvar süresini etkilemiş olabilecekleri için diğer regresyon metriklerini incelemek, muhtemelen daha verimli olur.
  • CPU süresi, CPU'nun kullanıcı kodunu yürütürken harcadığı süredir.

    • CPU süresi iki proje kaydında geriliyorsa bir Starlark CPU profili toplamanızı öneririz. Derlemeyi analiz aşamasıyla kısıtlamak için de muhtemelen --nobuild kullanmanız gerekir çünkü CPU ağır işlerin çoğu bu aşamada yapılır.
  • Sistem süresi, çekirdekteki CPU'nun harcadığı süredir.

    • Sistem saati gerilerse, Bazel dosya sisteminizdeki dosyaları okuduğunda çoğunlukla G/Ç ile bağıntılıdır.

Sistem genelinde yükleme profili oluşturma

JSON iz profil aracı, Bazel 6.0'da 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ındaki yüksek yük, Bazel'in makineniz için paralel olarak çok fazla yerel işlem planladığının bir göstergesi olabilir. Özellikle container ortamlarında (en azından #16512 birleşene kadar) --local_cpu_resources ve --local_ram_resources ayarlamalarına göz atabilirsiniz.

Bazel bellek kullanımını izleme

Bazel'in bellek kullanımını öğrenmek 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 bayt cinsinden kullanılan bellek miktarı.

    • Bazel karşılaştırması da bu metrik için karşılaştırmalar sağlar.
    • Buna ek olarak, peak-heap-size, max-heap-size, used-heap-size ve committed-heap-size mevcuttur (belgelere bakın) ancak bunlar daha az alakalıdır.
  • BEP'nin MemoryMetrics.peak_post_gc_heap_size: GC sonrası en yüksek JVM yığın boyutunun bayt cinsinden boyutu (tam GC'yi zorlamaya çalışan --memory_profile ayarını gerektirir).

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

Bazel'in bellek ayak izini daha ayrıntılı bir şekilde analiz etmek isterseniz kurallar için yerleşik bellek profil aracını 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 dillerde) bellek ayak izi sorunlu olabilir. Bazel, özellikle çalışanları hakkında metrikler toplar. WorkerMetrics.WorkerStats.worker_memory_in_kb alanı, çalışanların ne kadar bellek kullandığını gösterir (hatırlatma yoluyla).

JSON iz profil oluşturucu da --experimental_collect_system_network_usage işaretini (Bazel 6.0'da yeni özellik) ileterek çağrı sırasında kalıcı çalışan bellek kullanımını 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 (varsayılan 4) değerini düşürmek, kalıcı çalışanlar tarafından kullanılan bellek miktarının azalmasına yardımcı olabilir. Bazel'in 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ın daha az yapılması gerekecektir.

Uzaktan derlemeler için ağ trafiğini izleme

Uzaktan yürütmede Bazel, işlemlerin yürütülmesi sonucunda derlenen yapıları indirir. Bu nedenle, ağınızın bant genişliği derlemenizin performansını etkileyebilir.

Derlemeleriniz için uzaktan yürütme kullanıyorsanız çağrı sırasında BEP'nin NetworkMetrics.SystemNetworkStats protokolünü kullanarak ağ trafiğini izlemeyi düşünebilirsiniz (--experimental_collect_system_network_usage öğesinin iletilmesini gerektirir).

Ayrıca JSON izleme profilleri, --experimental_collect_system_network_usage işaretini (Bazel 6.0'daki yeni özellik) ileterek derleme süresince sistem genelindeki ağ kullanımını görüntülemenizi sağlar.

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ıldığında yüksek ancak sabit bir ağ kullanımı, ağın derlemenizdeki performans sorunundan kaynaklandığını gösterebilir. Zaten kullanmıyorsanız --remote_download_minimal parametresini ileterek Derlemeyi Bayt olmadan etkinleştirmeniz önerilir. 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.