Bazel'in paralel değerlendirme ve artımlılık modeli.
Veri modeli
Veri modeli aşağıdaki öğelerden oluşur:
SkyValue
. Düğüm olarak da adlandırılır.SkyValues
, derleme boyunca oluşturulan tüm verileri ve derlemenin girişlerini içeren sabit nesnelerdir. Örnekler: giriş dosyaları, çıkış dosyaları, hedefler ve yapılandırılmış hedefler.SkyKey
. BirSkyValue
öğesine referans veren kısa ve sabit bir ad (örneğin,FILECONTENTS:/tmp/foo
veyaPACKAGE://foo
).SkyFunction
. Anahtarlarına ve bağımlı düğümlerine göre düğüm oluşturur.- Düğüm grafiği. Düğümler arasındaki bağımlılık ilişkisini içeren bir veri yapısı.
Skyframe
. Bazel'ın temel aldığı artımlı değerlendirme çerçevesinin kod adı.
Değerlendirme
Derleme, derleme isteğini temsil eden düğüm değerlendirilerek gerçekleştirilir.
Bazel ilk olarak üst düzey SkyKey
anahtarına karşılık gelen SkyFunction
değerini bulur. İşlev daha sonra üst düzey düğümü değerlendirmek için ihtiyaç duyduğu düğümlerin değerlendirilmesini ister. Bu da yaprak düğümlerine ulaşılana kadar diğer SkyFunction
çağrılarıyla sonuçlanır. Yaprak düğümleri genellikle dosya sistemindeki
giriş dosyalarını temsil eder. Son olarak, Bazel üst düzey SkyValue
değerini, bazı yan etkileri (dosya sistemindeki çıkış dosyaları gibi) ve derlemede yer alan düğümler arasındaki bağımlılıkların yönlendirilmiş dairesel bir grafiğini elde eder.
SkyFunction
, işini yapması gereken tüm düğümleri önceden belirleyemezse birden fazla geçişte SkyKeys
isteğinde bulunabilir. Bunun basit bir örneği, sembolik bağlantı olan bir giriş dosyası düğümünü değerlendirmektir. İşlev, dosyayı okumaya çalışır, bunun bir sembolik bağlantı olduğunu anlar ve böylece sembolik bağlantının hedefini temsil eden dosya sistemi düğümünü getirir. Ancak bu kendisi bir sembolik bağlantı olabilir. Bu durumda, orijinal işlevin hedefini de getirmesi gerekir.
İşlevler kodda SkyFunction
arayüzü ve ona sağlanan hizmetler ise SkyFunction.Environment
adlı bir arayüzle temsil edilir. İşlevlerin yapabileceği şeyler şunlardır:
env.getValue
yöntemini çağırarak başka bir düğümün değerlendirilmesini isteyin. Düğüm kullanılabilir durumdaysa değeri döndürülür. Aksi takdirdenull
döndürülür ve işlevin denull
döndürmesi beklenir. İkinci durumda bağımlı düğüm değerlendirilir ve ardından orijinal düğüm oluşturucu tekrar çağrılır. Ancak bu kez aynıenv.getValue
çağrısı,null
olmayan bir değer döndürür.env.getValues()
yöntemini çağırarak diğer birden fazla düğümün değerlendirilmesini isteyin. Bağımlı düğümler paralel olarak değerlendirilmesi dışında, bu özellik temelde aynıdır.- Çağrı sırasında hesaplama yapma
- Dosya sistemine dosya yazma gibi yan etkileri olabilir. İki farklı işlevin birbirlerinin üzerine basmaktan kaçınmasına dikkat edilmelidir. Genel olarak, yazma yan etkileri (Bazel'den dışarı doğru veri akışı olduğunda) normal kabul edilir. Okuma yan etkileri (kayıtlı bir bağımlılık olmadan Bazel'e doğru veri akışı olduğu) kabul edilmez. Çünkü bunlar kayıtlı olmayan bir bağımlılıktır ve bu nedenle hatalı artımlı derlemelere neden olabilir.
İyi çalışan SkyFunction
uygulamaları, bağımlılık istemekten (dosya sistemini doğrudan okumak gibi) başka herhangi bir şekilde verilere erişmekten kaçınır. Bunun nedeni, Bazel'in okunan dosyaya veri bağımlılığını kaydetmemesine ve dolayısıyla hatalı artımlı derlemelere yol açması.
Bir işlev, işini yapmak için yeterli veriye sahip olduğunda, işlevin tamamlandığını belirten null
olmayan bir değer döndürmesi gerekir.
Bu değerlendirme stratejisinin bir dizi avantajı vardır:
- Hermetik. İşlevler yalnızca diğer düğümlere bağlı olarak giriş verileri istiyorsa Bazel, giriş durumu aynıysa aynı verilerin döndürüleceğini garanti edebilir. Tüm gökyüzü işlevleri belirleyiciyse bu, bütünün de belirleyici olacağı anlamına gelir.
- Doğru ve mükemmel artımlılık. Tüm işlevlerin giriş verilerinin tamamı kaydedilirse, Bazel yalnızca giriş verileri değiştiğinde geçersiz kılınması gereken tam düğüm grubunu geçersiz kılabilir.
- Paralellik. İşlevler yalnızca bağımlılık isteğinde bulunarak birbirleriyle etkileşim kurabildiğinden, birbirine bağımlı olmayan işlevler paralel olarak çalıştırılabilir ve Bazel, sonucun sıralı çalıştırılmış gibi elde edilecek sonuçlarla aynı olacağını garanti edebilir.
Artımlılık
İşlevler yalnızca diğer düğümlere bağlı olarak giriş verilerine erişebildiğinden, Bazel giriş dosyalarından çıkış dosyalarına kadar eksiksiz bir veri akışı grafiği oluşturabilir ve bu bilgileri yalnızca gerçekten yeniden oluşturulması gereken düğümleri yeniden oluşturmak için kullanabilir: değiştirilen giriş dosyaları kümesinin ters geçişli olarak kapanması.
Özellikle, olası iki artımlılık stratejisi vardır: aşağıdan yukarıya ve yukarıdan aşağıya. Hangisinin ideal olduğu, bağımlılık grafiğinin nasıl göründüğüne bağlıdır.
Aşağıdan yukarıya geçersiz kılma işlemi sırasında, bir grafik oluşturulduktan ve değiştirilen girişler kümesi bilindikten sonra, geçişli olarak değiştirilen dosyalara bağlı olan tüm düğümler geçersiz kılınır. Aynı üst düzey düğüm tekrar derlenecekse bu ideal bir seçenektir. Aşağıdan yukarıya geçersiz kılma işleminin, değiştirilip değiştirilmediğini belirlemek için önceki derlemenin tüm giriş dosyalarında
stat()
çalıştırmasını gerektirdiğini unutmayın. Değişen dosyalar hakkında bilgi edinmek içininotify
veya benzer bir mekanizma kullanılarak bu iyileştirme iyileştirilebilir.Yukarıdan aşağıya geçersiz kılma işlemi sırasında, üst düzey düğümün geçişli kapanması kontrol edilir ve yalnızca geçişli kapanışı temiz olan düğümler tutulur. Bu durum, düğüm grafiği büyükse daha iyidir ancak bir sonraki derleme için yalnızca küçük bir alt kümeye ihtiyaç vardır: Aşağıdan yukarıya geçersiz kılma işlemi, ikinci derlemenin küçük grafiğini gösteren yukarıdan aşağıya geçersiz kılma işleminin aksine, ilk derlemenin büyük grafiğini geçersiz kılar.
Bazel yalnızca aşağıdan yukarıya geçersiz kılma işlemi yapar.
Bazel, artımlılığı artırmak için değişiklik ayıklama yöntemini kullanır: Bir düğüm geçersiz kılınırsa ancak yeniden oluşturma işleminden sonra yeni değerinin eski değeriyle aynı olduğu keşfedilirse bu düğümdeki bir değişiklik nedeniyle geçersiz kılınan düğümler "yeniden dikilir".
Örneğin, kullanıcı bir C++ dosyasındaki bir yorumu değiştirirse bundan oluşturulan .o
dosyası aynı olur, bu nedenle bağlayıcının tekrar çağrılması gerekmez.
Artımlı Bağlantı / Derleme
Bu modelin ana sınırlaması, bir düğümün geçersiz kılınmasının ya hep ya hiç sorunu olmasıdır: Bir bağımlılık değiştiğinde, bağımlı düğüm her zaman en baştan yeniden oluşturulur. Bu, değişikliklere göre düğümün eski değerini değiştirecek daha iyi bir algoritma olsa bile geçerlidir. Aşağıda, bunun faydalı olacağı durumlara birkaç örnek verilmiştir:
- Artımlı bağlama
- Bir JAR dosyasında tek bir sınıf dosyası değiştiğinde, JAR dosyasını tekrar sıfırdan oluşturmak yerine yerinde değiştirmek mümkündür.
Bazel'ın bunları ilkeli bir şekilde desteklememesinin iki sebebi var:
- Sınırlı performans artışı gerçekleşti.
- Mutasyonun sonucunun temiz bir yeniden oluşturma sonucuyla aynı olduğunu doğrulamak zordur ve Google, bit bit tekrar tekrarlanabilen derlemelere değer verir.
Şimdiye kadar pahalı bir derleme adımını ayrıştırıp bu şekilde kısmi yeniden değerlendirme gerçekleştirerek yeterince iyi bir performans elde etmek mümkündü. Örneğin, bir Android uygulamasında tüm sınıfları birden çok gruba bölebilir ve ayrı ayrı dex ekleyebilirsiniz. Bu şekilde, bir gruptaki sınıflar değişmezse sıralama işleminin yeniden yapılması gerekmez.
Bazel kavramlarıyla eşleştirme
Burada, Bazel'ın bir derleme gerçekleştirmek için kullandığı anahtar SkyFunction
ve SkyValue
uygulamalarının üst düzey özeti bulunmaktadır:
- FileStateValue değeri.
lstat()
sonucu. İşlev, mevcut dosyalarda yapılan değişiklikleri algılamak için ek bilgileri de hesaplar. Skyframe grafiğindeki en düşük düzeyli düğümdür ve bağımlılığı yoktur. - FileValue değeri. Dosyanın gerçek içeriği veya çözümlenmiş yolu ile ilgilenen her şey tarafından kullanılır. Karşılık gelen
FileStateValue
ve çözülmesi gereken tüm sembolik bağlantılara bağlıdır (örneğin,a/b
içinFileValue
içina
çözümlenmiş yolu vea/b
için çözümlenmiş yol gerekir).FileValue
veFileStateValue
arasındaki ayrım, dosya içeriğinin gerçekten gerekli olmadığı durumlarda kullanılabilir. Örneğin, dosya sistemi glob'ları (srcs=glob(["*/*.java"])
gibi) değerlendirilirken dosya içerikleri alakasızdır. - DirectoryListingStateValue.
readdir()
sonucu.FileStateValue
gibi, bu düğüm de en düşük düzeyli düğümdür ve bağımlılığı yoktur. - DirectoryListingValue (Dizin Listeleme Değeri). Dizin girişleriyle ilgilenen her şey tarafından kullanılır. İlgili
DirectoryListingStateValue
ve dizinle ilişkiliFileValue
öğesine bağlıdır. - PackageValue. Bir BUILD dosyasının ayrıştırılmış sürümünü temsil eder. İlişkili
BUILD
dosyasınınFileValue
öğesine ve ayrıca paketteki glob'ları çözümlemek için kullanılan herhangi birDirectoryListingValue
öğesine (birBUILD
dosyasının içeriğini dahili olarak temsil eden veri yapısı) geçişli olarak bağlıdır. - ConfiguredTargetValue değerini döndürür. Yapılandırılmış hedefi temsil eder. Bu, bir hedefin analizi sırasında oluşturulan işlem grubunun ve bağımlı yapılandırılmış hedeflere sağlanan bilgilerin bir unsurudur. Karşılık gelen hedefin bulunduğu
PackageValue
, doğrudan bağımlılıklarınConfiguredTargetValues
ve derleme yapılandırmasını temsil eden özel bir düğüme bağlıdır. - ArtifactValue. Kaynak veya çıkış yapısı olması fark etmeksizin derlemedeki bir dosyayı temsil eder. Yapılar neredeyse dosyalara eşdeğerdir ve derleme adımlarının gerçek yürütülmesi sırasında dosyalara referans vermek için kullanılır. Kaynak dosyaları, ilişkili düğümün
FileValue
değerine, çıkış yapıları ise yapıyı oluşturan işleminActionExecutionValue
değerine bağlıdır. - ActionExecutionValue değerini döndürür. Bir eylemin yürütülmesini temsil eder. Giriş dosyalarının
ArtifactValues
değerine bağlıdır. Yürüttüğü işlem, SkyKeys'in içinde yer alır. Bu, SkyKeys'in küçük olması gerektiği kavramına aykırıdır. Yürütme aşaması çalışmazsaActionExecutionValue
veArtifactValue
kodlarının kullanılmadığını unutmayın.
Bu şema, görsel bir yardımcı olarak Bazel'ın kendi derlemesinden sonra SkyFunction uygulamaları arasındaki ilişkiyi göstermektedir: