Kalıcı Çalışanlar

Bu sayfada, kalıcı çalışanların nasıl kullanılacağı, avantajlar, gereksinimler ve çalışanların korumalı alanı nasıl etkilediği açıklanmaktadır.

Kalıcı çalışan, Bazel sunucusu tarafından uzun süredir devam eden bir işlemdir. Gerçek aracın (genellikle derleyici) etrafında bir sarmalayıcı işlevi görür veya aracın kendisidir. Kalıcı çalışanlardan yararlanmak için aracın bir dizi derleme yapmayı desteklemesi ve sarmalayıcının, aracın API'si ile aşağıda açıklanan istek/yanıt biçimi arasında çeviri yapması gerekir. Aynı çalışan, aynı derleme içinde --persistent_worker işaretiyle ve bu işaret olmadan çağrılabilir ve aracın uygun bir şekilde başlatılıp konuşulmasından ve çıkışta çalışanların kapatılmasından sorumludur. Her çalışan örneğine <outputBase>/bazel-workers altında ayrı bir çalışma dizini atanır (ancak hesaba çok amaçlı atanmaz).

Kalıcı çalışanların kullanılması, başlangıç ek yükünü azaltan, daha fazla JIT derlemesine olanak tanıyan ve örneğin, işlem yürütme sırasında soyut söz dizimi ağaçlarının önbelleğe alınmasını sağlayan bir yürütme stratejisidir. Bu strateji, uzun süreli bir sürece birden fazla istek göndererek bu iyileştirmelerden yararlanır.

Kalıcı çalışanlar Java, Scala, Kotlin ve daha birçok dilde uygulanır.

NodeJS çalışma zamanı kullanan programlar, çalışan protokolünü uygulamak için @bazel/worker yardımcı kitaplığını kullanabilir.

Kalıcı çalışanları kullanma

Bazel 0.27 ve sonraki sürümler, derlemeleri yürütürken varsayılan olarak kalıcı çalışanları kullanır ancak uzaktan yürütme önceliklidir. Bazel, kalıcı çalışanları desteklemeyen işlemlerde her işlem için bir araç örneği başlatmaya geri dönüyor. Geçerli araç hatıraları için worker stratejisini ayarlayarak derlemenizi açık bir şekilde kalıcı çalışanlar kullanacak şekilde ayarlayabilirsiniz. En iyi uygulama olarak bu örnek, worker stratejisine yedek olarak local öğesini belirtmeyi içerir:

bazel build //my:target --strategy=Javac=worker,local

Yerel strateji yerine çalışan stratejisini kullanmak, uygulamaya bağlı olarak derleme hızını önemli ölçüde artırabilir. Java'da derlemeler 2 ila 4 kat daha hızlı olabilir ve bazen ek derleme için daha fazla işlem yapılabilir. Bazel'ı derlemek çalışanlara göre yaklaşık 2,5 kat daha hızlı. Daha fazla bilgi için "Çalışan sayısını seçme" bölümüne bakın.

Yerel derleme ortamınızla eşleşen bir uzaktan derleme ortamınız da varsa uzaktan yürütme ve bir çalışan yürütme için yarışan deneysel dinamik stratejisini kullanabilirsiniz. Dinamik stratejiyi etkinleştirmek için --experimental_spawn_programr işaretini işaretleyin. Bu strateji, çalışanları otomatik olarak etkinleştirir. Bu nedenle worker stratejisini belirtmenize gerek yoktur, ancak yedek olarak local veya sandboxed özelliğini kullanmaya devam edebilirsiniz.

Çalışan sayısını seçme

Hatıra başına varsayılan çalışan örneği sayısı 4'tür ancak worker_max_instances işaretiyle ayarlanabilir. Mevcut CPU'lardan iyi şekilde yararlanmak ile JIT derleme ve önbellek isabetleri miktarı arasında bir denge vardır. Daha fazla çalışanla, daha fazla sayıda hedef Oluşturmanız gereken az sayıda hedef varsa tek bir çalışan, derleme hızı ve kaynak kullanımı arasında en iyi dengeyi sunabilir (örneğin, 8586 numaralı soruna bakın). worker_max_instances işareti, ipucu ve işaret grubu başına maksimum çalışan örneği sayısını (aşağı bakın) gösterir. Bu nedenle, varsayılan değeri korursanız karma sistemde çok fazla bellek kullanabilirsiniz. Artımlı derlemeler için birden fazla çalışan örneğinin avantajı daha da azdır.

Bu grafikte, 64 GB RAM'i olan 6 çekirdekli hiper iş parçacığı Intel Xeon 3,5 GHz Linux iş istasyonunda Bazel (hedef //src:bazel) için çizimden derleme süreleri gösterilmektedir. Her çalışan yapılandırması için beş temiz derleme çalıştırılır ve son dörtünün ortalaması alınır.

Temiz derlemelerin performans iyileştirmeleri grafiği

1. Şekil. Temiz derlemelerin performans iyileştirmeleri grafiği.

Bu yapılandırmada, iki çalışan en hızlı derlemeyi verir, ancak bir çalışana kıyasla yalnızca %14'lük iyileşme görülür. Daha az bellek kullanmak istiyorsanız tek bir çalışan iyi bir seçenektir.

Artımlı derleme genellikle daha da faydalıdır. Temiz derlemeler nispeten nadir görülse de derlemeler arasında tek bir dosyanın değiştirilmesi, özellikle teste dayalı geliştirmede özellikle yaygındır. Yukarıdaki örnekte, ek derleme süresini gölgelendiren Java dışı bazı paketleme işlemleri de vardır.

Yalnızca Java kaynaklarını yeniden derlemek için (//src/main/java/com/google/devtools/build/lib/bazel:BazelServer_deploy.jar) AbstractContainerizingSandboxedSpawn.java

Artımlı derlemelerin performans iyileştirmeleri grafiği

2. Şekil. Artımlı derlemelerin performans iyileştirmeleri grafiği.

Hızlanma, yapılan değişikliğe bağlıdır. Yaygın olarak kullanılan bir sabit değer değiştirildiğinde, yukarıdaki durumda 6 faktörlü hızlanma ölçülür.

Kalıcı çalışanları değiştirme

Çalışanlara başlangıç işaretleri belirtmek için --worker_extra_flag flag'ini, anahtarın içinde bulunduğu anahtarla belirtebilirsiniz. Örneğin, --worker_extra_flag=javac=--debug iletilmesi, yalnızca Javac için hata ayıklamayı etkinleştirir. Bu flag'in her kullanımı için yalnızca bir çalışan bayrağı ayarlanabilir ve yalnızca bir ipucu için ayarlanabilir. Çalışanlar yalnızca her anı için ayrı olarak oluşturulmaz, aynı zamanda başlangıç işaretlerindeki varyasyonlar için de oluşturulur. Her bir hatırlatıcı ve başlatma işareti kombinasyonu WorkerKey olarak birleştirilir ve her WorkerKey için en fazla worker_max_instances çalışan oluşturulabilir. İşlem yapılandırmasının kurulum işaretlerini nasıl belirtebileceğini görmek için sonraki bölüme bakın.

--high_priority_workers flag'ini, normal öncelikli annelikler yerine çalıştırılacak bir ipucu belirtmek için kullanabilirsiniz. Bu yaklaşım, her zaman kritik yolda olan işlemlere öncelik verebilir. İstekleri yürüten iki veya daha fazla yüksek öncelikli çalışan varsa diğer tüm çalışanların çalışması engellenir. Bu bayrak birden çok kez kullanılabilir.

--worker_sandboxing işaretinin iletilmesi, her çalışan isteğinin tüm girişleri için ayrı bir korumalı alan dizini kullanmasına neden olur. Korumalı alan ayarlamak, özellikle macOS'te biraz daha zaman alır ancak daha iyi bir doğruluk garantisi verir.

--worker_quit_after_build işareti esas olarak hata ayıklama ve profil oluşturma için yararlıdır. Bu flag, tüm çalışanları derleme tamamlandıktan sonra kapanmaya zorlar. Çalışanların yaptıklarıyla ilgili daha fazla sonuç almak için --worker_verbose aracını da iletebilirsiniz. Bu işaretleme, WorkRequest içindeki verbosity alanına yansıtılır. Böylece çalışan uygulamaları daha ayrıntılı olur.

Çalışanlar, günlüklerini <outputBase>/bazel-workers dizininde saklar (örneğin, /tmp/_bazel_larsrc/191013354bebe14fdddae77f2679c3ef/bazel-workers/worker-1-Javac.log). Dosya adı, çalışan kimliğini ve ipucunu içerir. Hatırlama başına birden fazla WorkerKey olabileceği için belirli bir ipucu için en fazla worker_max_instances günlük dosyası görebilirsiniz.

Android derlemeleri için Android Derlemesi Performans sayfasında ayrıntılara bakın.

Kalıcı çalışanları uygulama

Bir çalışanın nasıl oluşturulacağını öğrenmek için kalıcı çalışanlar oluşturma sayfasına bakın.

Bu örnekte, JSON kullanan bir çalışan için Starlark yapılandırması gösterilmektedir:

args_file = ctx.actions.declare_file(ctx.label.name + "_args_file")
ctx.actions.write(
    output = args_file,
    content = "\n".join(["-g", "-source", "1.5"] + ctx.files.srcs),
)
ctx.actions.run(
    mnemonic = "SomeCompiler",
    executable = "bin/some_compiler_wrapper",
    inputs = inputs,
    outputs = outputs,
    arguments = [ "-max_mem=4G",  "@%s" % args_file.path],
    execution_requirements = {
        "supports-workers" : "1", "requires-worker-protocol" : "json" }
)

Bu tanımda, bu işlemin ilk kullanımı /bin/some_compiler -max_mem=4G --persistent_worker komut satırını yürüterek başlar. Foo.java derlemek için istek şöyle görünür:

arguments: [ "-g", "-source", "1.5", "Foo.java" ]
inputs: [
  {path: "symlinkfarm/input1" digest: "d49a..." },
  {path: "symlinkfarm/input2", digest: "093d..."},
]

Çalışan, stdin alanında yeni satırla ayrılmış JSON biçiminde alır (requires-worker-protocol JSON olarak ayarlandığından). Daha sonra çalışan bu işlemi gerçekleştirir ve STCout'ta Bazel'e JSON biçimli bir WorkResponse gönderir. Daha sonra Bazel bu yanıtı ayrıştırıp manuel olarak bir WorkResponse protokolüne dönüştürür. JSON yerine ikili kodlamalı protobuf kullanarak ilişkili çalışanla iletişim kurmak için requires-worker-protocol şu şekilde ayarlanır: proto:

  execution_requirements = {
    "supports-workers" : "1" ,
    "requires-worker-protocol" : "proto"
  }

Yürütme koşullarına requires-worker-protocol öğesini dahil etmezseniz Bazel, çalışan iletişimini varsayılan olarak protobuf kullanacak şekilde ayarlar.

Bazel WorkerKey öğesini ipucu ve paylaşılan flag'lerden türetir. Bu nedenle, bu yapılandırma max_mem parametresinin değiştirilmesine izin verirse kullanılan her değer için ayrı bir çalışan oluşturulur. Çok fazla varyasyon kullanılırsa aşırı bellek tüketimine neden olabilir.

Her çalışan şu anda tek seferde yalnızca bir isteği işleyebilir. Deneysel Multiplex çalışanlar özelliği, temel araç çok iş parçalıysa ve sarmalayıcı bunu anlayacak şekilde ayarlanmışsa birden fazla ileti dizisinin kullanılmasına olanak tanır.

Bu GitHub deposunda, Java'da ve Python'da yazılmış örnek çalışan sarmalayıcılarını görebilirsiniz. JavaScript veya TypeScript üzerinde çalışıyorsanız @bazel/worker paketi ve nodejs çalışan örneği faydalı olabilir.

Çalışanlar, korumalı alanı nasıl etkiler?

Varsayılan olarak, worker stratejisi kullanıldığında işlem, local stratejisine benzer bir korumalı alanda çalıştırılmaz. --worker_sandboxing işaretini, tüm çalışanları korumalı alanlar içinde çalıştıracak şekilde ayarlayabilirsiniz. Böylece aracın her yürütme işleminin, olması gereken giriş dosyalarını görmesini sağlayabilirsiniz. Araç, önbellekler aracılığıyla dahili olarak istekler arasındaki bilgileri sızdırabilir. dynamic stratejisinin kullanılması için çalışanların korumalı alana alınması gerekir.

Derleyici önbelleklerinin çalışanlarla doğru şekilde kullanılmasına izin vermek için her giriş dosyasıyla birlikte bir özet iletilir. Bu nedenle, derleyici veya sarmalayıcı, dosyayı okumak zorunda kalmadan girişin hâlâ geçerli olup olmadığını kontrol edebilir.

İstenmeyen önbelleğe alma işlemlerine karşı koruma sağlamak için giriş özetleri kullanıldığında bile, korumalı alana sahip çalışanlar saf korumalı alana kıyasla daha az katı korumalı alan sağlar, çünkü araç önceki isteklerden etkilenen diğer dahili durumları koruyabilir.

Multiplex çalışanları, yalnızca çalışan uygulaması destekliyorsa korumalı alana alınabilir ve korumalı alan --experimental_worker_multiplex_sandboxing işaretiyle ayrı olarak etkinleştirilmelidir. Tasarım dokümanından daha fazla bilgi edinebilirsiniz).

Daha fazla bilgi

Kalıcı çalışanlar hakkında daha fazla bilgi için aşağıdaki konulara bakın: