Bu sayfada, kalıcı çalışanların nasıl kullanılacağı, avantajları, koşulları ve çalışanların korumalı alanı nasıl etkilediği ele alınmaktadır.
Kalıcı çalışan, Bazel sunucusu tarafından başlatılan uzun süreli bir işlemdir. Bu süreç, gerçek aracın (genellikle bir derleyici) etrafında sarmalayıcı görevi görür veya söz konusu aracın kendisidir. Kalıcı çalışanlardan yararlanmak için aracının bir dizi derleme yapmayı desteklemesi ve sarmalayıcının aracının API'si ile aşağıda açıklanan istek/yanıt biçimi arasında çeviri yapması gerekir. Aynı işçi, aynı derlemede --persistent_worker
işaretiyle ve işaretsiz olarak çağrılabilir. İşçi, aracı uygun şekilde başlatmaktan ve araçla konuşmaktan, ayrıca çıkışta işçileri kapatmaktan sorumludur. Her çalışan örneğine <outputBase>/bazel-workers
altında ayrı bir çalışma dizini atanır (ancak bu dizin başlatılmaz).
Kalıcı çalışanları kullanmak, başlatma ek yükünü azaltan, daha fazla JIT derlemesine olanak tanıyan ve işlem yürütmede örnek için 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üren bir işleme birden fazla istek göndererek bu iyileştirmeleri sağlar.
Kalıcı çalışanlar Java, Scala, Kotlin ve daha birçok dilde uygulanır.
NodeJS çalışma zamanı kullanan programlar, işleyici 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. Bununla birlikte, uzaktan yürütme önceliklidir. Kalıcı çalışanları desteklemeyen işlemlerde, Bazel her işlem için bir araç örneği başlatır. Geçerli araç anımsalları için worker
stratejiyi ayarlayarak derlemenizin kalıcı çalışanlar kullanacağını açıkça belirtebilirsiniz. En iyi uygulama olarak bu örnekte, worker
stratejisine yedek olarak local
belirtilmiştir:
bazel build //my:target --strategy=Javac=worker,local
Yerel strateji yerine çalışan stratejisi kullanmak, uygulamaya bağlı olarak derleme hızını önemli ölçüde artırabilir. Java için derlemeler 2-4 kat daha hızlı olabilir, bazen de artımlı derleme için daha hızlı olabilir. Çalışanlara kıyasla Bazel'i derlemek yaklaşık 2,5 kat daha hızlıdır. Daha fazla bilgi için "Çalışanların sayısını seçme" bölümüne bakın.
Yerel derleme ortamınızla eşleşen uzak bir derleme ortamınız da varsa uzaktan yürütme ve işleyici yürütme işlemlerini yarıştıran deneysel dinamik stratejiyi kullanabilirsiniz. Dinamik stratejiyi etkinleştirmek için --experimental_spawn_scheduler işaretini geçin. Bu strateji, işçileri otomatik olarak etkinleştirir. Bu nedenle, worker
stratejisini belirtmeniz gerekmez. Ancak yedek olarak local
veya sandboxed
'yi kullanmaya devam edebilirsiniz.
Çalışan sayısını seçme
Anımsatıcı başına varsayılan çalışan örneği sayısı 4'tür ancak worker_max_instances
işaretiyle ayarlanabilir. Mevcut CPU'lardan iyi bir şekilde yararlanmak ve JIT derlemesi ile önbellek isabetlerinin miktarı arasında bir denge vardır. Daha fazla çalışanla, daha fazla hedef, JIT'siz kod çalıştırma ve soğuk önbelleğe alma işlemlerinin başlangıç maliyetlerini karşılar. Oluşturulacak az sayıda hedefiniz varsa derleme hızı ile kaynak kullanımı arasındaki en iyi dengeyi tek bir çalışan verebilir (örneğin, 8586 numaralı soruna bakın).
worker_max_instances
işareti, anımsatıcı ve işaret grubu başına maksimum çalışan örneği sayısını belirler (aşağıya bakın). Bu nedenle, karma bir sistemde varsayılan değeri korursanız oldukça fazla miktarda bellek kullanabilirsiniz. Artımlı derlemelerde birden çok çalışan örneğinin avantajı daha da azdır.
Bu grafikte, 64 GB RAM'e sahip 6 çekirdekli hiper iş parçacıklı Intel Xeon 3,5 GHz Linux iş istasyonunda Bazel'in (hedef //src:bazel
) sıfırdan 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 derlemenin ortalaması alınır.
Şekil 1. Temiz derlemelerin performans iyileştirmeleri grafiği.
Bu yapılandırmada, iki çalışan en hızlı derlemeyi sağlar. Bir çalışana kıyasla yalnızca %14 iyileşme görülür. Daha az bellek kullanmak istiyorsanız bir çalışan iyi bir seçenektir.
Artımlı derleme genellikle daha da fazla avantaj sağlar. Temiz derlemeler nispeten nadirdir ancak özellikle test odaklı geliştirmede, derlemeler arasında tek bir dosyanın değiştirilmesi yaygın karşılaşılan bir durumdur. Yukarıdaki örnekte, artımlı derleme süresini gölgeleyebilecek bazı Java dışı paketleme işlemleri de vardır.
AbstractContainerizingSandboxedSpawn.java dosyasında dahili bir dize sabitinin değiştirilmesinden sonra yalnızca Java kaynaklarını yeniden derlemek (//src/main/java/com/google/devtools/build/lib/bazel:BazelServer_deploy.jar
), 3 kat hızlanma sağlar (bir ısıtma derlemesi atlanarak ortalama 20 artımlı derleme):
Şekil 2. Artımlı derlemelerdeki performans iyileştirmelerini gösteren grafik.
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 faktör 6'nın hızı ölçülür.
Kalıcı çalışanları değiştirme
--worker_extra_flag
işaretini, çalışanlara başlatma bayraklarını belirtmek için mnemonic ile anahtarlanmıştır. Örneğin, --worker_extra_flag=javac=--debug
parametresini iletmek yalnızca Javac için hata ayıklamayı etkinleştirir.
Bu işaretin her kullanımı için yalnızca bir işçi işareti ve yalnızca bir anımsatıcı ayarlanabilir.
Çalışanlar yalnızca her bir hatırlatıcı için ayrı ayrı değil, aynı zamanda başlangıç işaretlerindeki varyasyonlar için de ayrı ayrı oluşturulur. Her bir kısaltma ve başlangıç işareti kombinasyonu bir 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ği hakkında bilgi edinmek için sonraki bölüme bakın.
Normal öncelikli anımsamalara göre çalışması gereken bir hatırlatıcı belirtmek için --high_priority_workers
işaretini kullanabilirsiniz. Bu sayede her zaman kritik yolda olan işlemlere öncelik verebilirsiniz. İ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 işaret birden çok kez kullanılabilir.
--worker_sandboxing
işaretçisi iletildiği takdirde her çalışan isteği, tüm girişleri için ayrı bir korumalı alan dizini kullanır. Korumalı alan oluşturmak, özellikle macOS'te biraz daha zaman alır ancak daha doğru sonuçlar elde etmenizi sağlar.
--worker_quit_after_build
işareti, temel olarak hata ayıklama ve profil oluşturma işlemleri için kullanışlıdır. Bu işaret, derleme tamamlandığında
tüm çalışanları işi bırakmaya zorlar. Çalışanların neler yaptığı hakkında daha fazla çıktı almak için --worker_verbose
aracını da iletebilirsiniz. Bu işaret, WorkRequest
dilindeki verbosity
alanına yansıtılarak çalışan uygulamalarının daha ayrıntılı olmasına da olanak tanır.
Çalışanlar günlüklerini <outputBase>/bazel-workers
dizininde (ör. /tmp/_bazel_larsrc/191013354bebe14fdddae77f2679c3ef/bazel-workers/worker-1-Javac.log
) depolar.
Dosya adı, çalışan kimliğini ve anımsatıcıyı içerir. Her anımsatıcı için birden fazla WorkerKey
olabilir. Bu nedenle, belirli bir anımsatıcı için worker_max_instances
'ten fazla günlük dosyası görebilirsiniz.
Android derlemeleri için Android Derleme Performansı sayfasında ayrıntıları inceleyin.
Kalıcı çalışanları hayata geçirme
Çalışan oluşturma hakkında daha fazla bilgi için Kalıcı çalışanlar oluşturma sayfasına bakın.
Bu örnekte, JSON kullanan bir işleyici 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ım doğrultusunda, bu işlemin ilk kullanımı /bin/some_compiler -max_mem=4G --persistent_worker
komut satırının yürütülmesiyle başlar. Foo.java
derleme isteği şu şekilde görünür:
NOT: Protokol arabelleği spesifikasyonu "yılan büyük/küçük harf" (request_id
) kullanırken, JSON protokolünde "deve büyük/küçük harf" (requestId
) kullanılır. Bu dokümanda, JSON örneklerinde büyük/küçük harf kullanılır, ancak protokolden bağımsız olarak alan hakkında konuşurken yılan büyük/küçük harf kullanılır.
{
"arguments": [ "-g", "-source", "1.5", "Foo.java" ]
"inputs": [
{ "path": "symlinkfarm/input1", "digest": "d49a..." },
{ "path": "symlinkfarm/input2", "digest": "093d..." },
],
}
Çalışan, bunu stdin
üzerinde yeni satırla sınırlandırılmış JSON biçiminde alır (requires-worker-protocol
JSON olarak ayarlandığından). Daha sonra çalışan, işlemi gerçekleştirir ve stdout'unda Bazel'e JSON biçimli bir WorkResponse
gönderir. Daha sonra Bazel bu yanıtı ayrıştırır ve manuel olarak WorkResponse
protosuna dönüştürür. İlişkili çalışanla JSON yerine ikili kodlu protobuf kullanarak iletişim kurmak için requires-worker-protocol
, proto
olarak şu şekilde ayarlanır:
execution_requirements = {
"supports-workers" : "1" ,
"requires-worker-protocol" : "proto"
}
Yürütme şartlarına requires-worker-protocol
öğesini dahil etmezseniz Bazel varsayılan olarak çalışan iletişimini protobuf kullanacak şekilde ayarlar.
Bazel, WorkerKey
öğesini anımsatıcılardan ve paylaşılan işaretlerden türetir. Dolayısıyla bu yapılandırma, max_mem
parametresinin değiştirilmesine izin veriyorsa kullanılan her değer için ayrı bir çalışan oluşturulur. Çok fazla varyasyon kullanılırsa bu durum, aşırı bellek tüketimine neden olabilir.
Her çalışan şu anda bir seferde yalnızca bir isteği işleyebilir. Deneysel çoklu işleyici özelliği, temel araç çoklu iş parçacıklıysa ve sarmalayıcı bunu anlayacak şekilde ayarlandıysa birden fazla iş parçacığı kullanılmasına olanak tanır.
Bu GitHub deposunda, Java ve Python'da yazılan örnek çalışan sarmalayıcılarını görebilirsiniz. JavaScript veya TypeScript ile çalışıyorsanız @bazel/worker paketi ve nodejs worker örneği faydalı olabilir.
İşçiler korumalı alanı nasıl etkiler?
Varsayılan olarak worker
stratejisi kullanıldığında işlem, local
stratejisine benzer şekilde bir korumalı alanda çalıştırılmaz. --worker_sandboxing
işaretini korumalı alan içindeki tüm çalışanları çalıştıracak şekilde ayarlayabilirsiniz. Böylece, aracın her yürütmesinin yalnızca olması gereken giriş dosyalarını gördüğünden emin olursunuz. Araç, istekler arasında dahili olarak (örneğin, bir önbellek aracılığıyla) bilgi sızdırabilir. dynamic
stratejisini kullanmak için çalışanların korumalı alana yerleştirilmesi gerekir.
Derleyici önbelleklerinin çalışanlarla doğru şekilde kullanılmasını sağlamak için her giriş dosyasıyla birlikte bir özet iletilir. Böylece derleyici veya sarmalayıcı, dosyayı okumak zorunda kalmadan girişin hâlâ geçerli olup olmadığını kontrol edebilir.
İstenmeyen önbelleğe almayı korumak için giriş özetleri kullanılırken bile, korumalı alana alınan çalışanlar yalnızca korumalı alana göre daha az katı korumalı alan sunar. Bunun nedeni, araç önceki isteklerden etkilenen diğer dahili durumları koruyabilmesidir.
Multiplex çalışanları, yalnızca çalışan uygulaması destekliyorsa korumalı alana alınabilir. Bu korumalı alan, --experimental_worker_multiplex_sandboxing
işaretiyle ayrı olarak etkinleştirilmelidir. Daha fazla ayrıntı için tasarım dokümanındaki bilgileri inceleyin.
Daha fazla bilgi
Kalıcı çalışanlar hakkında daha fazla bilgi için bkz:
- Orijinal kalıcı çalışanlar blog yayını
- Haskell uygulama açıklaması {: .external}
- Blog yayını: Mike Morearty {: .external}
- Bazel ile Kullanıcı Arabirimi Geliştirme: Asana ile Angular/TypeScript ve Kalıcı Çalışanlar {: .external}
- Bazel stratejileri {: .external}
- bazel-tartışma posta listesinde bilgilendirici çalışan stratejisi tartışması {: .external}