Çerçeve

Sorun bildirin Kaynağı göster

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 süresince 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. SkyValue öğesine referans veren kısa, sabit bir addır. Örneğin, FILECONTENTS:/tmp/foo veya PACKAGE://foo.
  • SkyFunction. Anahtarlarına ve bağımlı düğümlere göre düğümler oluşturur.
  • Düğüm grafiği. Düğümler arasındaki bağımlılık ilişkisini içeren bir veri yapısı.
  • Skyframe. Artımlı değerlendirme çerçevesinin kod adı Bazel'ın temel aldığı koddur.

Değerlendirme

Derleme, derleme isteğini temsil eden düğümün değerlendirilmesinden oluşur (bu, üzerinde çalıştığımız durum olsa da çok fazla eski kod bulunmaktadır). İlk olarak SkyFunction öğesi bulunur ve üst düzey SkyKey anahtarıyla çağrılır. İşlev, ardından üst düzey düğümü değerlendirmek için gereken düğümlerin değerlendirilmesini ister. Bu da diğer işlev çağrılarıyla sonuçlanır ve yaprak düğümlerine (genellikle dosya sistemindeki giriş dosyalarını temsil eden düğümler) ulaşılana kadar bu şekilde devam eder. Son olarak ü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ş bir döngüsel grafiğini elde ederiz.

Bir SkyFunction, ihtiyacı olan tüm düğümlerin işini yapması için önceden karar veremezse birden fazla geçişte SkyKeys isteğinde bulunabilir. Basit bir örnek, sembolik bir 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 bir sembolik bir bağlantı olabilir. Bu durumda, orijinal işlevin hedefini de getirmesi gerekir.

İşlevler, kodda SkyFunction arayüzü ve bu arayüze SkyFunction.Environment adı verilen bir arayüz tarafından sağlanan hizmetler ile temsil edilir. İşlevlerin yapabileceği işlemler şunlardır:

  • env.getValue öğesini çağırarak başka bir düğümün değerlendirilmesini isteyin. Düğüm kullanılabilir durumdaysa değeri döndürülür. Aksi durumda null döndürülür ve işlevin kendisinin null değerini 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 dışında bir değer döndürür.
  • env.getValues() öğesini çağırarak başka düğümlerin değerlendirilmesini isteyin. Bağımlı düğümlerin paralel olarak değerlendirilmesi dışında bu da temelde aynıdır.
  • Çağrı sırasında hesaplama yapma
  • Dosya sistemine dosya yazma gibi yan etkileri vardır. İki farklı işlevin birbirinin ayağına basmaması gerekir. Genel olarak, yazma yan etkileri (verilerin Bazel'den dışarı çıktığı durumlarda) sorun oluşturmaz. Okunan yan etkiler (kayıtlı bir bağımlılık olmadan Bazel'e doğru giden veriler), kaydedilmemiş bir bağımlılık olduklarından ve dolayısıyla yanlış artımlı derlemelere neden olabileceğinden, okumayan etkilerin (kayıtlı bir bağımlılık olmadan Bazel'a doğru gittiği) doğru olmaz.

SkyFunction uygulamaları verilere bağımlılık istemekten başka bir yöntemle (ör. dosya sistemini doğrudan okumak gibi) erişmemelidir. Bunun nedeni, Bazel'in okunan dosyaya veri bağımlılığını kaydetmemesi ve bu nedenle yanlış artımlı derlemelere yol açmasıdır.

Bir işlev işini yapmak için yeterli veriye sahip olduğunda, tamamlandığını belirten null dışında bir değer döndürmelidir.

Bu değerlendirme stratejisinin bazı avantajları vardır:

  • Hermetiklik. İşlevler yalnızca giriş verilerini diğer düğümlere bağlı olarak istiyorsa Bazel, giriş durumunun aynı olması durumunda aynı verilerin döndürüleceğini garanti edebilir. Tüm gökyüzü fonksiyonları deterministikse bu, tüm yapının da deterministik olacağı anlamına gelir.
  • Artımlılık doğru ve mükemmel olmalıdır. 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 isteyerek birbiriyle etkileşimde bulunabildiğinden, birbirine bağımlı olmayan işlevler paralel olarak çalıştırılabilir ve Bazel, sonucun sıralı olarak çalıştırılıyormuş gibi 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 eksiksiz bir veri akışı grafiği oluşturabilir ve bu bilgileri yalnızca gerçekten yeniden oluşturulması gereken düğümleri (değiştirilen giriş dosyaları kümesinin ters geçişli kapanması) yeniden oluşturmak için kullanabilir.

Özellikle, iki olası artımlılık stratejisi vardır: aşağıdan yukarıya ve yukarıdan aşağıya. Bağımlılık grafiğinin nasıl göründüğüne bağlı olarak hangisinin en uygun seçenek olması gerektiğidir.

  • Aşağıdan yukarıya geçersiz kılma sırasında, bir grafik oluşturulduktan ve değiştirilen giriş grubu bilindikten sonra, değiştirilen dosyalara bağlı olarak tüm düğümler geçersiz kılınır. Aynı üst düzey düğümün yeniden oluşturacağını biliyorsak bu en uygun 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ırılmasını gerektirdiğini unutmayın. Bu durum, değiştirilen dosyalar hakkında bilgi edinmek için inotify veya benzer bir mekanizma kullanılarak iyileştirilebilir.

  • Yukarıdan aşağıya geçersiz kılma 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. Mevcut düğüm grafiğinin büyük olduğunu bilirsek ancak bir sonraki derlemede bu grafiğin yalnızca küçük bir alt kümesine ihtiyacımız olursa daha iyi sonuç alırsınız: Aşağıdan yukarıya geçersiz kılma, ikinci derlemenin küçük grafiğinde yürüyen yukarıdan aşağıya geçersiz kılmanın aksine ilk derlemenin büyük grafiğini geçersiz kılar.

Şu anda yalnızca aşağıdan yukarıya geçersiz kılma gerçekleştiriyoruz.

Daha fazla artımlılık elde etmek için değişiklik budama yöntemini kullanırız: Bir düğüm geçersiz kılınırsa ancak yeniden oluşturma sonrasında yeni değerinin eski değeriyle aynı olduğu belirlenir ve bu düğümdeki bir değişiklik nedeniyle geçersiz kılınan düğümler "yeniden dirildi".

Bu, örneğin, bir C++ dosyasındaki yorum değiştirildiğinde yararlı olur: Ondan oluşturulan .o dosyası aynı olur ve bu yüzden bağlayıcıyı tekrar çağırmamız 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ç" mantığında olmasıdır: Bir bağımlılık değiştiğinde, değişikliklere göre düğümün eski değerini değiştirecek daha iyi bir algoritma olsa bile bağımlı düğüm her zaman sıfırdan yeniden oluşturulur. Bunun yararlı olabileceği birkaç örnek:

  • Artımlı bağlantı
  • Bir .jar içinde tek bir .class dosyası değiştiğinde, .jar dosyasını yeniden sıfırdan oluşturmak yerine teorik olarak değiştirebiliriz.

Bazel'in şu anda bu özellikleri ilkeli bir şekilde desteklememesinin (artımlı bağlantı desteğimiz olmasına rağmen Skyframe'de uygulanmamasının) iki nedeni var: Performansta yalnızca sınırlı bir kazanç elde ettik ve değişikliğin net bir yeniden oluşturmanın sonucunun aynı olacağını garanti etmek zordu. Google, bitmek üzere tekrarlanabilir derlemelere değer veriyor.

Şimdiye kadar yalnızca pahalı bir derleme adımını ayrıştırıp kısmi yeniden değerlendirme yaparak her zaman yeterince iyi bir performans elde edebiliyorduk. Bu yöntemin uygulanması, bir uygulamadaki tüm sınıfları birden çok gruba ayırıyor ve bunları ayrı ayrı yapıyor. Böylece, bir gruptaki sınıflar değişmezse dexing işleminin yeniden yapılması gerekmez.

Bazel kavramlarıyla eşleme

Aşağıda, Bazel'in derleme gerçekleştirmek için kullandığı SkyFunction uygulamalarından bazılarına ilişkin kaba bir genel bakış verilmiştir:

  • FileStateValue değerine ayarlayın. lstat() sonucu. Mevcut dosyalar için, dosyada yapılan değişiklikleri tespit etmek üzere ek bilgileri de hesaplarız. Bu, Skyframe grafiğindeki en düşük seviyeli düğümdür ve bağımlılığı yoktur.
  • FileValue (Dosya Değeri). Bir dosyanın gerçek içeriğini ve/veya çözümlenmiş yolunu önemseyen her şey tarafından kullanılır. Karşılık gelen FileStateValue öğesine ve çözülmesi gereken sembolik bağlantılara (örneğin a/b için FileValue, a öğesinin çözümlenen yolunu ve a/b çözümlenmiş yolunu gerektirir) bağlıdır. Bazı durumlarda (örneğin, srcs=glob(["*/*.java"]) gibi dosya sistemi glob'larının (örneğin, srcs=glob(["*/*.java"])) dosya içeriklerinin değerlendirilmesi gerçekten gerekli olmadığı için FileStateValue arasındaki ayrım önemlidir.
  • DirectoryListingValue aracılığıyla güncelleyin. Bu, temelde readdir() işlevinin sonucudur. Dizinle ilişkilendirilmiş FileValue öğesine bağlıdır.
  • PackageValue. BUILD dosyasının ayrıştırılmış sürümünü gösterir. İlişkili BUILD dosyasının FileValue öğesine ve ayrıca paketteki glob'ları (bir BUILD dosyasının içeriğini dahili olarak temsil eden veri yapısı) çözmek için kullanılan tüm DirectoryListingValue'ye bağlıdır.
  • ConfiguredTargetValue alt değeri. Yapılandırılmış bir hedefi temsil eder. Bu hedef, bir hedefin analizi sırasında oluşturulan işlem kümesinin ve buna bağlı olan yapılandırılmış hedeflere sağlanan bilgilerin bir alt kümesidir. İlgili hedefin bulunduğu PackageValue, doğrudan bağımlılıkların ConfiguredTargetValues ve derleme yapılandırmasını temsil eden özel bir düğüme bağlıdır.
  • ArtifactValue. Kaynak veya çıkış yapıları olması fark etmeksizin, derlemedeki bir dosyayı temsil eder (yapılar, dosyalarla neredeyse eşdeğerdir ve derleme adımlarının yürütülmesi sırasında dosyalara referans vermek için kullanılır). Kaynak dosyalarda bu, ilişkili düğümün FileValue değerine bağlıdır. Çıkış yapılarında ise yapıyı oluşturan işlemin ActionExecutionValue değerine bağlıdır.
  • ActionExecutionValue. Bir işlemin yürütülmesini temsil eder. Giriş dosyalarının ArtifactValues öğesine bağlıdır. Yaptığı işlem o anda gökyüzü anahtarının içinde yer alıyor. Bu durum, gökyüzü tuşlarının küçük olması gerektiği kavramına aykırıdır. Bu tutarsızlığı çözmeye çalışıyoruz (Skyframe'de yürütme aşamasını yürütmezsek ActionExecutionValue ve ArtifactValue'ın kullanılmayacağını unutmayın).