Çerçeve

Sorun bildirin Kaynağı göster Gece · 7,4 , 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Bazel'in paralel değerlendirme ve artımlı model.

Veri modeli

Veri modeli aşağıdaki öğelerden oluşur:

  • SkyValue Düğüm olarak da adlandırılır. SkyValues, derleme sırasında oluşturulan tüm verileri ve derlemenin girişlerini içeren değişmez nesnelerdir. Örnekler: giriş dosyaları, çıkış dosyaları, hedefler ve yapılandırılmış belirler.
  • SkyKey Bir SkyValue öğesini referans göstermek için kısa ve sabit bir ad. Örneğin, FILECONTENTS:/tmp/foo veya PACKAGE://foo.
  • SkyFunction. Anahtarlarına ve bağımlı düğümlerine göre düğüm oluşturur.
  • Düğüm grafiği. Nodlar arasındaki bağımlılık ilişkisini içeren bir veri yapısı.
  • Skyframe Artımlı değerlendirme çerçevesi Bazel'in kod adı: seçmeniz gerekir.

Değerlendirme

Derleme, derleme isteğini temsil eden düğümü değerlendirmekten oluşur (Bu, ulaşmaya çalıştığımız durumdur ancak bu yolda çok fazla eski kod vardır). Öncelikle SkyFunction bulunur ve üst düzey SkyKey anahtarıyla çağrılır. Ardından işlev, üst düzey düğümü değerlendirmek için ihtiyaç duyduğu düğümlerin değerlendirilmesini ister. Bu da, yaprak düğümlere (genellikle dosya sistemindeki giriş dosyalarını temsil eden düğümler) ulaşılana kadar diğer işlev çağrılarına neden olur. Son olarak, üst düzey SkyValue değerini, bazı yan etkileri (ör. dosya sistemindeki çıkış dosyaları) ve derleme işlemine dahil olan düğümler arasındaki bağımlılıkların yönlendirilmiş döngüsüz grafiğini elde ederiz.

Bir SkyFunction, ihtiyacı olan tüm düğümlerin işini yapacağını önceden bildiremezse birden fazla geçişte SkyKeys isteğinde bulunabilir. Basit bir örnek, bir sembolik bağlantı olduğu ortaya çıkan bir giriş dosyası düğümünü değerlendirmektir: İşlev dosyayı okumaya çalışır, 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 çağrısı yaparak başka bir düğümün değerlendirilmesini isteyin. Düğüm kullanılabilir durumdaysa değeri döndürülür, aksi takdirde null döndürülür ve işlevin kendisinin null döndürmesi beklenir. İkinci durumda, bağımlı düğüm değerlendirilir ve ardından orijinal düğüm oluşturucu yeniden çağrılır ancak bu kez aynı env.getValue çağrısı null olmayan bir değer döndürür.
  • env.getValues() çağrısı yaparak diğer birden fazla düğümün değerlendirilmesini isteyin. Bu yöntem, bağımlı düğümlerin paralel olarak değerlendirilmesi dışında temel olarak aynı işlemi gerçekleştirir.
  • Ç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ıya aktığı durumlar) kabul edilir. Okuma yan etkileri (verilerin kayıtlı bir bağımlılık olmadan Bazel'e içeriye aktığı durumlar) ise kayıtlı bir bağımlılık olmadığı ve bu nedenle yanlış artımlı derlemelere neden olabileceği için kabul edilmez.

SkyFunction uygulamaları, verilere bağımlılık isteğinde bulunmaktan (ör. dosya sistemini doğrudan okuyarak) başka bir şekilde erişmemelidir. Aksi takdirde Bazel, veri bağımlılığını okunan dosyaya kaydetmez ve bu da yanlış artımlı derlemelere neden olur.

Bir işlev, görevini yapacak kadar veriye sahip olduğunda, tamamlanmayı belirten null olmayan bir değer döndürmelidir.

Bu değerlendirme stratejisinin çeşitli avantajları vardır:

  • Hermetiklik. İş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ü 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 tüm giriş verileri kaydedilirse Bazel, giriş verileri değiştiğinde yalnızca geçersiz kılınması gereken düğüm kümesini geçersiz kılar.
  • 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 tekrar oluşturacağını biliyorsak bu en uygun seçenektir. Aşağıdan yukarı doğru geçersiz kılma işleminde, önceki derlemenin tüm giriş dosyalarında stat()'ün çalıştırılarak değiştirilip değiştirilmediğinin belirlenmesi gerektiğini unutmayın. Değişen dosyalar hakkında bilgi edinmek için inotify veya benzer bir mekanizma kullanılarak bu durum 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 biliyoruz ancak sonraki derlemede yalnızca küçük bir alt kümesine ihtiyacımız varsa bu yöntem daha iyidir: Aşağıdan yukarı doğru geçersiz kılma, yalnızca ikinci derlemenin küçük grafiğini gezen yukarıdan aşağı doğru geçersiz kılma işleminin aksine, ilk derlemenin daha büyük grafiğini geçersiz kılar.

Şu anda yalnızca aşağıdan yukarı doğru geçersiz kılma işlemi yapıyoruz.

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ğlama/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 sonucuyla aynı olacağını garanti etmek zordu. Google, bitmek üzere tekrarlanabilir derlemelere sahip.

Ş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 her birindekileri 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. İlgili FileStateValue'e ve çözülmesi gereken tüm sembolik bağlantılara bağlıdır (örneğin, a/b için FileValue, a'in ve a/b'nin çözüldüğü yola ihtiyaç duyar). Bazı durumlarda (örneğin, dosya sistemi glob'larını (srcs=glob(["*/*.java"]) gibi) değerlendirme) dosyanın içeriğine gerçekten ihtiyaç duyulmadığı 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. Bir BUILD dosyasının ayrıştırılmış sürümünü temsil eder. İ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. Yapılandırılmış hedef, bir hedefin analizi sırasında oluşturulan işlemler grubunun ve yapılandırılmış hedeflere sağlanan, bu hedefe bağlı bilgilerin bir tuple'sidir. İ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ı (yapılar neredeyse dosyalarla eşdeğerdir ve derleme adımlarının gerçekte yürütülmesi sırasında dosyalara referans vermek için kullanılır) olsun, derlemedeki bir dosyayı temsil eder. 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ığı çözmek için çalışıyoruz (Skyframe'da yürütme aşamasını çalıştırmazsak ActionExecutionValue ve ArtifactValue'un kullanılmadığını unutmayın).