Derleme performansını ayırma

Bazel karmaşıktır ve derleme sırasında birçok farklı işlem yapar. Bu işlemlerden bazıları derleme performansını etkileyebilir. Bu sayfada, bu Bazel kavramlarından bazılarını derleme performansı üzerindeki etkileriyle eşleştirmeye çalışılmaktadır. Kapsamlı olmasa da metrikleri ayıklayarak derleme performansıyla ilgili sorunları nasıl tespit edebileceğiniz ve bunları düzeltmek için neler yapabileceğinizle ilgili bazı örnekler ekledik. Bu bilgilerle, derleme performansındaki gerilemeleri incelerken bu kavramları uygulayabileceğinizi umuyoruz.

Temiz derleme ve artımlı derleme

Temiz derleme, her şeyi sıfırdan derlerken artımlı derleme, tamamlanmış işlerin bir kısmını yeniden kullanır.

Özellikle Bazel'in önbelleklerinin durumuna bağlı metrikler (ör. derleme isteği boyutu metrikleri) topladığınız / birleştirdiğiniz durumlarda temiz ve artımlı derlemelere ayrı ayrı bakmanızı öneririz. Ayrıca, bunlar iki farklı kullanıcı deneyimini temsil eder. Sıfırdan temiz bir derleme başlatmaya kıyasla (soğuk önbellek nedeniyle daha uzun sürer) geliştiriciler kod üzerinde yineleme yaptığından artımlı derlemeler çok daha sık gerçekleşir (önbellek genellikle zaten sıcak 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 derlemedir. Aksi takdirde, bunu genel olarak artımlı bir derleme olarak sınıflandırabiliriz. Kullanıcı, farklı işaretlere veya farklı hedeflere geçmiş olabilir ve bu da etkili bir şekilde temiz bir derlemeye neden olabilir. Artışın daha katı bir tanımı büyük olasılıkla bir sezgisel yöntem şeklinde olacaktır. Örneğin, yüklenen paketlerin sayısına (PackageMetrics.packages_loaded) bakılabilir.

Derleme performansının yerine derleme metriklerini kullanma

Belirli metriklerin (ör. Bazel'in CPU süresi veya uzak bir kümedeki kuyruk süreleri) deterministik olmayan yapısı nedeniyle derleme performansını ölçmek zor olabilir. Bu nedenle, Bazel'in yaptığı iş miktarının bir vekili olarak deterministik metrikleri kullanmak faydalı olabilir. Bu da Bazel'in performansını etkiler.

Derleme isteğinin boyutu, derleme performansını önemli ölçüde etkileyebilir. Daha büyük bir derleme, derleme grafiklerinin analiz edilmesi ve oluşturulması için daha fazla çalışma gerektirebilir. Daha fazla bağımlılık eklenip oluşturulduğundan derlemelerin organik büyümesi geliştirme sürecinde doğal olarak gerçekleşir. Bu nedenle, derlemelerin karmaşıklığı artar ve oluşturulması daha maliyetli hâle gelir.

Bu sorunu çeşitli derleme aşamalarına ayırabilir ve her aşamada yapılan iş için aşağıdaki metrikleri vekil metrik olarak kullanabiliriz:

  1. PackageMetrics.packages_loaded: Başarıyla yüklenen paket sayısı. Buradaki bir regresyon, yükleme aşamasında her ek BUILD dosyasının okunması ve ayrıştırılması için daha fazla çalışma yapılması gerektiğini gösterir.

    • Bunun nedeni genellikle bağımlılıkların eklenmesi ve bunların geçişli kapanışının yüklenmesi gerekmesidir.
    • Yeni bağımlılıkların nereye eklenmiş olabileceğini bulmak için query / cquery'yi kullanın.
  2. TargetMetrics.targets_configured: Derlemede yapılandırılan hedef ve yön sayısını gösterir. Regresyon, yapılandırılmış hedef grafiğin oluşturulması ve geçilmesi için daha fazla çalışma gerektiğini gösterir.

    • Bu durum genellikle bağımlılıkların eklenmesinden ve bunların geçişli kapanma grafiğinin oluşturulmasından kaynaklanır.
    • Yeni bağımlılıkların nereye eklenmiş olabileceğini bulmak için cquery'yi kullanın.
  3. ActionSummary.actions_created: Derlemede oluşturulan işlemleri gösterir. Regresyon, işlem grafiğinin oluşturulmasında daha fazla çalışmayı ifade eder. Bu sayıya, yürütülmemiş olabilecek kullanılmayan işlemlerin de dahil olduğunu unutmayın.

  4. ActionSummary.actions_executed: Gerçekleştirilen işlem sayısı. Bir regresyon, bu işlemlerin yürütülmesinde doğrudan daha fazla iş yapılması anlamına gelir.

    • BEP, en çok gerçekleştirilen işlem türlerini gösteren işlem istatistiklerini ActionData yazar. Varsayılan olarak, en çok kullanılan 20 işlem türü toplanır. Ancak, bu verileri yürütülen tüm işlem türleri için toplamak üzere --experimental_record_metrics_for_all_mnemonics değerini iletebilirsiniz.
    • Bu, hangi tür işlemlerin (ek olarak) yürütüldüğünü anlamanıza yardımcı olur.
  5. BuildGraphSummary.outputArtifactCount: Yürütülen işlemlerle oluşturulan yapay nesnelerin sayısı.

    • Yürütülen işlem sayısı artmadıysa 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 birinde gerileme yaşanmasının, toplam süre, CPU süresi ve bellek kullanımında da gerilemeye yol açabileceğini belirtmek isteriz.

Yerel kaynakların kullanımı

Bazel, yerel makinenizde çeşitli kaynaklar kullanır (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 derleme işlemini ve diğer görevleri gerçekleştirirken performansını / kullanılabilirliğini etkileyebilir.

Harcanan süre

Gürültüden en çok etkilenen ve derlemeden derlemeye büyük ölçüde değişebilen metrikler zamandır. Özellikle de toplam süre, CPU süresi ve sistem zamanı. Bu metrikler için bir karşılaştırma ölçütü elde etmek üzere bazel-bench'i kullanabilirsiniz. Yeterli sayıda --runs ile ölçümünüzün istatistiksel anlamlılığını artırabilirsiniz.

  • Toplam süre, geçen gerçek dünya süresidir.

    • Yalnızca toplam süre geriliyorsa JSON izleme profili toplamanızı ve farklılıkları aramanızı öneririz. Aksi takdirde, duvar süresini etkilemiş olabilecek diğer gerileyen 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üdü arasında gerilerse Starlark CPU profili toplamanızı öneririz. Ayrıca, derlemeyi analiz aşamasıyla sınırlamak için --nobuild kullanmanız da önerilir. Çünkü CPU'nun yoğun olarak kullanıldığı işlemlerin çoğu bu aşamada yapılır.
  • Sistem süresi, CPU'nun çekirdekte geçirdiği süredir.

    • Sistem saati gerilerse bu durum, Bazel'in dosya sisteminizden dosya okuduğu sırada genellikle G/Ç ile ilişkilidir.

Sistem genelinde yük profili oluşturma

Bazel 6.0'da kullanıma sunulan --experimental_collect_load_average_in_profiler işaretini kullanan JSON izleme profil oluşturucu, çağırma 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.

Bir Bazel çağrısı sırasında yüksek yük olması, Bazel'in makineniz için çok fazla yerel işlemi paralel olarak planladığını gösterebilir. Özellikle kapsayıcı ortamlarda (en azından #16512 birleştirilene kadar) --local_cpu_resources ve --local_ram_resources değerlerini ayarlamayı düşünebilirsiniz.

Bazel bellek kullanımını izleme

Bazel'in bellek kullanımını elde etmek 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 belleğin bayt cinsinden miktarı.

    • Bazel bench bu metrik için de karşılaştırma verileri sağlar.
    • Ayrıca peak-heap-size, max-heap-size, used-heap-size ve committed-heap-size (belgelere bakın) vardır ancak bunlar daha az alakalıdır.
  • BEP'nin MemoryMetrics.peak_post_gc_heap_size: GC sonrası bayt cinsinden en yüksek JVM yığın boyutunun boyutu (tam GC'yi zorlamaya çalışan --memory_profile ayarlanmasını gerektirir).

Bellek kullanımındaki gerileme genellikle derleme isteği boyutu metriklerindeki gerilemenin bir sonucudur. Bu durum genellikle bağımlılıkların eklenmesinden veya kural uygulamasındaki bir değişiklikten kaynaklanır.

Bazel'in bellekte kapladığı yeri daha ayrıntılı bir düzeyde analiz etmek için kurallarda yerleşik bellek profil oluşturucuyu kullanmanızı öneririz.

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

Kalıcı çalışanlar, derlemelerin önemli ölçüde hızlanmasına yardımcı olsa da (özellikle yorumlanan diller için) bellek ayak izleri 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ı (anımsatıcıya göre) gösterir.

JSON izleme profil oluşturucu, --experimental_collect_system_network_usage işaretini (Bazel 6.0'da yeni) ileterek çağırma sırasında 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 düşürmek (varsayılan değer 4), kalıcı çalışanlar tarafından kullanılan bellek miktarını azaltmaya yardımcı olabilir. Gelecekte bu tür ince ayarların daha az yapılması için Bazel'in kaynak yöneticisini ve planlayıcısını daha akıllı hale getirmek üzere çalışmalarımızı sürdürüyoruz.

Uzak derlemeler için ağ trafiğini izleme

Uzaktan yürütmede Bazel, işlemleri yürütmenin 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 kullanıyorsanız BEP'den NetworkMetrics.SystemNetworkStats proto'yu kullanarak çağırma sırasında ağ trafiğini izlemeyi düşünebilirsiniz (--experimental_collect_system_network_usage iletmek gerekir).

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

Uzak yürütme kullanılırken yüksek ancak nispeten sabit bir ağ kullanımı, derlemenizde darboğazın ağ olduğunu gösterebilir. Henüz kullanmıyorsanız --remote_download_minimal ileterek baytlar olmadan derleme özelliğini etkinleştirmeyi düşünebilirsiniz. Bu, gereksiz ara yapıtların indirilmesini önleyerek derlemelerinizi hızlandırır.

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