Bu sayfada kalıcı çalışanların nasıl kullanılacağı, avantajları, gereksinimleri ve çalışanların korumalı alanı nasıl etkilediği açıklanmaktadır.
Kalıcı işleyici, Bazel sunucusu tarafından başlatılan ve gerçek araç (genellikle bir derleyici) etrafında sarmalayıcı olarak işlev gören veya aracı kendisi olan uzun süreli bir işlemdir. 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ı çalışan, aynı derlemede --persistent_worker
işaretiyle ve olmadan çağrılabilir. Aracı uygun şekilde başlatmak ve araçla konuşmaktan ve çıkışta çalışanları 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üreli bir sürece birden fazla istek göndererek bu iyileştirmeleri gerçekleştirir.
Kalıcı çalışanlar Java, Scala, Kotlin ve daha birçok dil için 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 çalıştırırken varsayılan olarak kalıcı çalışanları kullanır ancak uzaktan çalıştırma önceliklidir. Kalıcı çalışanları desteklemeyen işlemler için Bazel, her işlem için bir araç örneği başlatır. Geçerli araç anımsatıcıları için worker
stratejisini ayarlayarak derlemenizi kalıcı çalışanları kullanacak şekilde açıkça ayarlayabilirsiniz. En iyi uygulama olarak bu örnekte, worker
stratejisinin yedeği olarak local
belirtilmesi dahildir:
bazel build //my:target --strategy=Javac=worker,local
Yerel strateji yerine işçi stratejisinin kullanılması, uygulamaya bağlı olarak derleme hızını önemli ölçüde artırabilir. Java için derlemeler 2-4 kat daha hızlı olabilir. Artımlı derlemede bu süre bazen daha da uzayabilir. Ç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 bir uzaktan derleme ortamınız varsa uzaktan yürütme ve çalışan yürütme yöntemini kullanan deneysel dinamik stratejisini 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
Her anımsatıcı için varsayılan çalışan örneği sayısı 4'tür ancak worker_max_instances
işaretiyle ayarlanabilir. Mevcut CPU'ları iyi kullanma ile aldığınız JIT derleme ve önbellek isabetlerinin miktarı arasında bir denge vardır. Daha fazla çalışan olduğunda, daha fazla hedef, JIT'siz kod çalıştırma ve soğuk önbellekleri kullanmayla ilgili başlangıç maliyetlerini karşılar. Derlemeniz gereken az sayıda hedef varsa tek bir çalışan, derleme hızı ile kaynak kullanımı arasında en iyi dengeyi sağlayabilir (ö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ştirmelerini gösteren grafik.
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 derlemeler arasında tek bir dosyanın değiştirilmesi, özellikle test odaklı geliştirmede yaygındır. 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ı derlemelerin performans iyileştirmelerinin grafiği.
Hızlanma, yapılan değişikliğe bağlıdır. Yukarıdaki durumda, yaygın olarak kullanılan bir sabit değiştiğinde 6 kat hızlanma ölçülür.
Kalıcı çalışanları değiştirme
Çalışanlara başlangıç işaretlerini belirtmek için --worker_extra_flag
işaretini iletebilirsiniz. Örneğin, --worker_extra_flag=javac=--debug
geçildiğinde yalnızca Javac için hata ayıklama etkinleştirilir.
Bu işaretin kullanımı başına ve yalnızca bir anımsatıcı için yalnızca bir çalışan işareti 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ğini öğrenmek 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, her zaman kritik yolda olan işlemlere öncelik vermenize yardımcı olabilir. İ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şaretini geçmek, her çalışan isteğinin tüm girişleri için ayrı bir korumalı alan dizini kullanmasına neden olur. Korumalı alanın oluşturulması özellikle macOS'te biraz daha zaman alır ancak daha iyi doğruluk garantisi verir.
--worker_quit_after_build
işareti, çoğunlukla hata ayıklama ve profil oluşturma için yararlı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 depolar (ör. /tmp/_bazel_larsrc/191013354bebe14fdddae77f2679c3ef/bazel-workers/worker-1-Javac.log
).
Dosya adı, çalışan kimliğini ve anımsatıcıyı içerir. Anımsatıcı başına birden fazla WorkerKey
olabileceğinden belirli bir anımsatıcı için worker_max_instances
taneden fazla günlük dosyası görebilirsiniz.
Android derlemeleriyle ilgili ayrıntıları Android Derleme Performansı sayfasında bulabilirsiniz.
Kalıcı çalışanları uygulama
Çalışan oluşturma hakkında daha fazla bilgi için kalıcı çalışan 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 spesifikasyonunda "alt tireli" (request_id
) kullanılırken JSON protokolünde "büyük/küçük harfli" (requestId
) kullanılır. Bu dokümanda, JSON örneklerinde büyük/küçük harfli, protokolden bağımsız olarak alandan bahsederken ise alt tireli 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. Ardından Bazel bu yanıtı ayrıştırır ve manuel olarak WorkResponse
proto'ya dönüştürür. JSON yerine ikili kodlu protobuf kullanarak ilişkili işleyiciyle iletişim kurmak için requires-worker-protocol
, aşağıdaki gibi proto
olarak ayarlanır:
execution_requirements = {
"supports-workers" : "1" ,
"requires-worker-protocol" : "proto"
}
requires-worker-protocol
'ü yürütme koşullarına eklemezseniz Bazel, varsayılan olarak işçi iletişiminde protobuf'i kullanır.
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 yol açabilir.
Her çalışan şu anda bir seferde yalnızca bir isteği işleyebilir. Temel araç çok iş parçacıklıysa ve sarmalayıcı bunu anlayacak şekilde ayarlanmışsa deneysel Multiplex çalışanları özelliği, birden çok iş parçacığının kullanılmasına olanak tanır.
Bu GitHub deposunda, Java ve Python'da yazılmış örnek işleyici 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
stratejisinin kullanılması, local
stratejisine benzer şekilde işlemi bir korumalı alanda çalıştırmaz. --worker_sandboxing
işaretini, tüm işleyicileri korumalı alan içinde çalıştıracak şekilde ayarlayarak aracın her çalıştırmasında yalnızca olması gereken giriş dosyalarının gösterilmesini sağlayabilirsiniz. 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ıyı tasarım belgesinde bulabilirsiniz.)
Daha fazla bilgi
Kalıcı çalışanlar hakkında daha fazla bilgi için aşağıdakilere bakın: