İçeriğe geç
academia.sh

Ders 11 / 12

Depo Öznitelikleri

Öznitelik dosyası hangi işlemin hangi dosyada nasıl davranacağını belirler: ayarsız bin işlemelik tarihçe 5888 nesne yazar, satır sonu 162 gereksiz nesne üretir ve elli birleştirmenin 43'ü üretilen dosyada çakışarak 86 nesne daha ekler.

İçindekiler

Önceki dersin ölçümü bir varsayımı dışarıda bıraktı: çalışma alanına çıkarılan dosyaların iki düzende de aynı olduğu varsayımını. Bu, dosyanın nasıl yazıldığının bir tercih olmadığını söylüyordu.

Öyle değildir. Nesne deposundaki damla ile çalışma alanındaki dosya birbirinin aynısı olmak zorunda değildir; arada bir dönüşüm katmanı vardır ve o katman yapılandırılabilir. Katman ayarsız bırakıldığında sessizce çalışır ve yaptığı iş tarihçeye yazılır. Bu dersin sorusu şudur: hangi öznitelik hangi işlemi hangi dosyada değiştirir, ve ayarsız durumda içeriği değişmediği hâlde kaç nesne yazılır?

Öznitelik Dosyası Neyi Belirler

Depo öznitelikleri (repository attributes), dosya desenlerine davranış bağlayan kurallardır ve .gitattributes dosyasında dururlar. Dosya işlenen bir dosyadır: tarihçeye girer, dallar arasında farklılaşabilir ve klonlayan herkese aynı kuralı taşır. Yapılandırma dosyasından ayıran yer burasıdır — yapılandırma kişiseldir ve kopyaya özeldir, öznitelik depoya aittir.

# öznitelik dosyası — örnek döküm, çalıştırılmamıştır

# .gitattributes
*            text=auto
*.py         text eol=lf
*.md         text eol=lf
ayar.py      text merge=ours
sunum.bin    -text -diff
belge.md     diff=metin

Her satır bir desen ve ona bağlı niteliklerdir. text dosyanın metin sayılacağını ve satır sonu dönüşümüne girebileceğini bildirir; text=auto kararı içeriğe bakarak aracın vermesini ister. eol=lf çalışma alanına yazılırken hangi satır sonu (line ending) düzeninin kullanılacağını sabitler. Başındaki eksi işareti niteliği kaldırır: -text dosyanın hiçbir dönüşüme girmeyeceğini, -diff ise karşılaştırmanın metin olarak denenmeyeceğini bildirir. merge=ours ve diff=metin ise bir birleştirme sürücüsüne (merge driver) ya da bir karşılaştırma tanımına ad verir.

Dört İşlem, Dört Ayrı An

Öznitelikler dört ayrı anda devreye girer ve hangisinin ne zaman çalıştığı karışırsa ölçüm de karışır.

Çıkarma anı: damla çalışma alanına yazılırken satır sonu dönüşümü uygulanır. İşleme anı: çalışma alanındaki dosya damlaya çevrilirken ters dönüşüm uygulanır — depoya yazılan biçim tektir. Birleştirme anı: iki yanın değişikliği harmanlanırken hangi sürücünün kullanılacağı belirlenir. Karşılaştırma anı: iki damla arasındaki fark üretilirken metin sayılıp sayılmayacağı belirlenir.

Beşinci bir an daha vardır ve tarihçeyi hiç ilgilendirmez: deponun bir sürümü arşiv olarak paketlenirken hangi yolların dışarıda bırakılacağı da bir öznitelikle bildirilir. Kural paketlemeye bakar, işlemeye değil; dosya tarihçede kalır, yalnız arşive girmez. Bu ders onu ölçmüyor çünkü nesne birimiyle karşılığı yoktur.

İlk ikisi tarihçeye nesne yazar; son ikisinden yalnız birleştirme yazar. Karşılaştırma okunabilirliği etkiler, tarihçeyi etkilemez — bu yüzden ölçümde -diff satırı sıfır verir ve bu bir eksiklik değil, doğru sonuçtur.

Satır sonu dönüşümü ayarsızken ne olur? Depoya, yazanın ortamında ne varsa o girer. İki ayrı satır sonu düzeni kullanan iki ortam aynı dosyaya sırayla dokunduğunda, içerik hiç değişmese bile damla baştan yazılır: bayt dizisi farklıdır, dolayısıyla nesne farklıdır.

Ölçümün Varsayımları

  • BD20 — Ölçüm ortak kurgunun dört ölçeğini kullanır. Her işlemeye ayrı bir üreteçten iki alan eklenir: yazanın satır sonu düzeni ve içeriğin gerçekten değişip değişmediği.
  • BD21 — İşlemelerin üçte biri ayrı bir satır sonu düzeni kullanan bir ortamdan gelir; beşte biri içeriği gerçekten değiştirmez, yalnız dosyaya dokunur.
  • BD22 — Satır sonu ayarı yokken, içeriği değişmemiş bir işleme ancak dosyanın son kaydedilen düzeni farklıysa yeni damla yazar; her böyle yazım 2 nesnedir. Ayar varsayıldığında bu işlemeler 0 nesne yazar.
  • BD23 — Her 20 işlemede bir birleştirme yapılır; pencerenin iki yarısı da üretilen dosyaya dokunduysa birleştirme çakışması doğar. Elle çözüm bir işleme yazar, 2 nesne.
  • BD24merge=ours tanımlandığında çakışma doğmaz ve çözüm işlemesi yazılmaz; sürücü üretilen dosyada karşı yanın sürümünü almaz.
  • BD25-text ve -diff ikili varlığa hiçbir nesne eklemez ve hiçbirini çıkarmaz; etkileri çıkarma ve karşılaştırma anındadır, tarihçede değil.
  • BD26 — Bedel dokunulan nesne birimiyle sayılır. “Ayarsız” sütunu taban, “tam ayarlı” sütunu ortak kurgunun klon bedelidir; aradaki fark özniteliğin yazılmasını engellediği nesnedir.

Ölçüm

"""Depo oznitelikleri: ayarsiz durumda dogan gereksiz nesne.

Bolum 1 - hangi oznitelik hangi dosyada hangi islemi degistiriyor (1000 isleme).
Bolum 2 - dort olcekte ayarsiz, satir sonu ayarli ve tam ayarli nesne.
"""
TOHUM = 20260814
DOSYALAR = ("olcum.py", "rapor.py", "kimlik.py", "ayar.py", "belge.md")
IKILI_VARLIK = "sunum.bin"
URETILEN = "ayar.py"      # uretilen dosya: birlestirme surucusu buna baglanir
OLCEKLER = (50, 200, 1000, 4000)
BIRLESME_ARALIGI = 20     # her 20 islemede bir birlestirme


def uretec(tohum):
    d = tohum % 2147483646 + 1

    def r(n):
        nonlocal d
        d = (d * 48271) % 2147483647
        return d % n
    return r


def tarihce(n, tohum=TOHUM):
    """n islemelik dogrusal tarihce; her isleme bir dosyaya dokunuyor."""
    r, liste = uretec(tohum), []
    for i in range(n):
        dosya = DOSYALAR[r(5)]
        ikili = r(11) == 0
        liste.append({"no": i + 1, "dosya": dosya, "ikili": ikili,
                      "nesne": 2 + (40 if ikili else 0)})
    return liste


def klon_bedeli(t, ikili_dahil=True):
    return sum(x["nesne"] for x in t if ikili_dahil or not x["ikili"])


def ortamli(t, tohum):
    """Her islemeye yazanin satir sonu duzeni ve icerigin gercekten degisip
    degismedigi eklenir."""
    r, k = uretec(tohum), []
    for x in t:
        k.append({**x, "crlf": r(3) == 0, "gercek": r(5) != 0})
    return k


def satir_sonu_nesnesi(k, dosya=None):
    """Ayarsizken: icerik ayni oldugu halde satir sonu duzeni degistigi icin
    yeniden yazilan damla. Dosya basina son duzen izlenir."""
    son, gereksiz = {}, 0
    for x in k:
        if x["dosya"] == dosya or dosya is None:
            if not x["gercek"] and son.get(x["dosya"]) not in (None, x["crlf"]):
                gereksiz += 2
        son[x["dosya"]] = x["crlf"]
    return gereksiz


def cakisan_birlesmeler(k):
    """Her aralikta bir birlestirme; iki yan da uretilen dosyaya dokunduysa
    cakisma dogar ve elle cozum bir isleme yazar."""
    sayi = 0
    for bas in range(0, len(k) - BIRLESME_ARALIGI + 1, BIRLESME_ARALIGI):
        pencere = k[bas:bas + BIRLESME_ARALIGI]
        yarim = BIRLESME_ARALIGI // 2
        sol = any(x["dosya"] == URETILEN for x in pencere[:yarim])
        sag = any(x["dosya"] == URETILEN for x in pencere[yarim:])
        sayi += sol and sag
    return sayi


def surucu_nesnesi(k):
    return 2 * cakisan_birlesmeler(k)


K = ortamli(tarihce(1000), TOHUM + 7)
print("dosya       oznitelik        degistirdigi islem        satir sonu nesnesi"
      "  surucu nesnesi")
OZNITELIK = (("olcum.py", "text eol=lf", "cikarma ve isleme"),
             ("rapor.py", "text eol=lf", "cikarma ve isleme"),
             ("kimlik.py", "text eol=lf", "cikarma ve isleme"),
             ("ayar.py", "text merge=ours", "cikarma, isleme, birlestirme"),
             ("belge.md", "text eol=lf", "cikarma ve isleme"),
             (IKILI_VARLIK, "-text -diff", "cikarma ve karsilastirma"))
for dosya, oz, islem in OZNITELIK:
    s = 0 if dosya == IKILI_VARLIK else satir_sonu_nesnesi(K, dosya)
    d = surucu_nesnesi(K) if dosya == URETILEN else 0
    print(f"  {dosya:10s} {oz:16s} {islem:26s} {s:16d} {d:15d}")
print()
print("isleme  ayarsiz nesne  satir sonu ayarli  tam ayarli  gereksiz nesne   oran")
for n in OLCEKLER:
    k = ortamli(tarihce(n), TOHUM + 7)
    tam, s, d = klon_bedeli(k), satir_sonu_nesnesi(k), surucu_nesnesi(k)
    print(f"{n:6d} {tam + s + d:14d} {tam + d:18d} {tam:11d} {s + d:15d} "
          f"{(s + d) / (tam + s + d):6.4f}")
print()
n = 1000
k = ortamli(tarihce(n), TOHUM + 7)
print(f"tarihce {n} isleme; satir sonu yuzunden yeniden yazilan damla "
      f"{satir_sonu_nesnesi(k) // 2}, yazdigi nesne {satir_sonu_nesnesi(k)}")
print(f"birlestirme {n // BIRLESME_ARALIGI}, uretilen dosyada cakisan "
      f"{cakisan_birlesmeler(k)}, elle cozumun yazdigi nesne {surucu_nesnesi(k)}")
dosya       oznitelik        degistirdigi islem        satir sonu nesnesi  surucu nesnesi
  olcum.py   text eol=lf      cikarma ve isleme                        38               0
  rapor.py   text eol=lf      cikarma ve isleme                        34               0
  kimlik.py  text eol=lf      cikarma ve isleme                        22               0
  ayar.py    text merge=ours  cikarma, isleme, birlestirme               36              86
  belge.md   text eol=lf      cikarma ve isleme                        32               0
  sunum.bin  -text -diff      cikarma ve karsilastirma                  0               0

isleme  ayarsiz nesne  satir sonu ayarli  tam ayarli  gereksiz nesne   oran
    50            390                384         380              10 0.0256
   200            972                938         920              52 0.0535
  1000           5888               5726        5640             248 0.0421
  4000          23578              22912       22600             978 0.0415

tarihce 1000 isleme; satir sonu yuzunden yeniden yazilan damla 81, yazdigi nesne 162
birlestirme 50, uretilen dosyada cakisan 43, elle cozumun yazdigi nesne 86

Hangi Öznitelik Hangi Dosyada

Üst tablo dersin birinci sorusunu yanıtlıyor ve dikkat çeken şey sütunların birbirinden bağımsız olmasıdır.

Satır sonu sütunu beş metin dosyasına dağılıyor: 38, 34, 22, 36 ve 32 — toplam 162 nesne. Dağılım eşit değil ama nedeni özniteliğin kendisi değil, kurgunun dosya dağılımı. Öznitelik açısından beş satır aynı kuralı taşıyor; ödenen bedel dosyanın ne sıklıkta dokunulduğuna göre değişiyor.

Sürücü sütunu tek bir satırda toplanıyor: 86 nesne, yalnız ayar.py satırında. Bu, kurgu gereği üretilen dosyadır — elle yazılmayan, bir araç tarafından üretilip depoya konan bir dosya. Öbür dört dosyada sürücü sütunu 0’dır çünkü onlarda çakışma elle çözülmelidir ve çözüm bir karardır, ayarla değiştirilecek bir şey değildir.

İkili varlık satırı iki sütunda da 0 veriyor. -text ve -diff nitelikleri gerçek işler yapar — dönüşümü engeller, okunmaz karşılaştırmayı önler — ama tarihçeye tek nesne eklemez ve çıkarmaz. Ölçünün birimi nesne olduğu için o etkiler burada görünmez. Bu satır, ölçünün kapsam sınırının bildirimidir.

Ayarsızlığın Ödettiği

Alt tablonun birimi dokunulan nesnedir ve üç sütun aynı tarihçenin üç ayarlama düzeyini veriyor. Bin işlemelik tarihçe ayarsız 5888 nesne yazıyor; satır sonu ayarlandığında 5726’ya, birleştirme sürücüsü de tanımlandığında 5640’a — yani ortak kurgunun klon bedeline — iniyor. Gereksiz nesne 248, oran 0,0421.

Oran küçüktür ve bu, ölçümün dürüst sonucudur: satır sonu düzensizliği bir depoyu şişirmez. İki gözlem yine de kayda değer. Birincisi, gereksiz nesne oranı dört ölçekte 0,0256, 0,0535, 0,0421 ve 0,0415 çıkıyor; büyük iki ölçekte 0,042 dolayında oturuyor ve ölçek büyüdükçe azalmıyor. Bu, tarihçenin ömrü boyunca ödenmeye devam eden bir bedeldir. İkincisi, elli işlemelik satırdaki 10 nesne, o ölçekteki 1/50 çözünürlüğün yanında beş işlemeye karşılık gelir; küçük depoda bu bedelden bir sonuç çıkarılamaz.

Asıl sayı üçüncü satırda duruyor: 50 birleştirmenin 43’ü üretilen dosyada çakışıyor. Bu, birleştirmelerin beşte dördünden fazlasıdır ve her biri bir kişinin oturup çakışma işaretlerini elle temizlemesi demektir. Tarihçeye yazdığı 86 nesne bu işin en küçük parçasıdır; ölçülmeyen kısmı, kırk üç kez verilen ve hiçbirinin bir bilgi taşımadığı karardır. Dallanma ve İşbirliği kursu çakışma çözümünün tarihçeye yazılmadığını göstermişti — burada görülen şey, o yazılmayan kararların kırk üç tanesinin baştan gereksiz olduğudur.

Hangi Satır Kazanır

Ölçüm her dosyaya tek bir kural düştüğünü varsaydı. Gerçek bir öznitelik dosyasında bir yola birden çok desen uyar ve hangisinin kazandığı bilinmeden hiçbir ayarın etkisi öngörülemez.

Kural sırası üç katmanlıdır. Aynı dosya içinde son eşleşen satır kazanır — yukarıdan aşağı okunur ve alttaki üsttekini ezer; bu yüzden genel desenler başa, özel desenler sona yazılır. Alt dizindeki öznitelik dosyası üsttekini ezer, çünkü daha yakındır. Ve deponun içinde, tarihçeye girmeyen yerel bir öznitelik dosyası daha vardır; o hepsini ezer ve yalnız o kopyada geçerlidir.

Üçüncü katman iki yönlü keskindir. Bir kopyanın davranışını depoyu değiştirmeden ayarlamayı sağlar; aynı nedenle, bir kopyada beklenmedik bir dönüşüm görüldüğünde bakılacak ilk yer orasıdır. Öznitelikler depoya aittir demiştik — bu, o yerel katman dışında doğrudur ve farkın nerede olduğu bilinmezse bir dosyanın neden başka türlü çıktığı hiç anlaşılmaz.

Bir nitelik üç değer alabilir: verilmiş (text), kaldırılmış (-text) ve belirtilmemiş. Üçüncüsü ikinciyle aynı şey değildir: kaldırılmış bir nitelik kararı kesinleştirir, belirtilmemiş bir nitelik kararı bir alt katmana ya da aracın kendi öntanımına bırakır. text=auto tam olarak bu üçüncü durumu yönetir — kararı içeriğe bakarak verir ve ikili sandığı dosyaya dönüşüm uygulamaz.

Ayarın Sınırı ve Kurtarma

Öznitelik dosyası ileriye dönük çalışır. Bugün yazılan bir text=auto satırı, dün yazılmış damlaları düzeltmez; tarihçedeki 162 nesne yerinde kalır. Ayarın etkisi ilk çıkarmadan sonra başlar ve depo çalışanların ellerinde zaten çıkarılmış durumdaysa, dosyaların bir kez yeniden normalize edilmesi gerekir — bu, tarihçede yeni bir işleme olarak görünür ve tarihçeyi yeniden yazmaz.

Yeniden yazan yol da vardır ve konunun ikinci dersindeki kuralla aynı sınıra girer: geçmişteki bütün damlaları normalize etmek tarihçeyi yeniden yazmaktır, kimlikleri değiştirir, geri alınamaz ve her kopyanın yeniden klonlanmasını gerektirir. Kazancı ölçümde okunuyor — 162 nesne. Bin işlemelik bir depoda bu, klon bedelinin otuz beşte biri kadardır ve o kazanç için tarihçeyi yeniden yazmak neredeyse hiçbir durumda haklı çıkmaz.

Ucuz ve geri alınabilir yol şudur: öznitelik dosyası deponun ilk gününde yazılır; sonradan yazıldıysa tek bir normalizasyon işlemesiyle ileriye dönük düzeltilir; geçmiş olduğu gibi bırakılır. Yanlış bir öznitelik satırının kendisi ise zararsızdır — dosya işlenen bir dosya olduğu için satır geri alınabilir, ve dönüşüm bir sonraki çıkarmada eski hâline döner.

Özet

  • Depo öznitelikleri işlenen bir dosyada durur ve depoya aittir; yapılandırmadan farkı budur. Dört ayrı anda devreye girerler: çıkarma, işleme, birleştirme ve karşılaştırma.
  • Karşılaştırma anı tarihçeye nesne yazmaz; ikili varlık satırı ölçümde iki sütunda da 0 verir ve bu, ölçünün kapsam sınırının bildirimidir.
  • Satır sonu ayarsızken içeriği değişmemiş 81 işleme yeni damla yazar ve 162 nesne üretir; beş metin dosyasına 38 / 34 / 22 / 36 / 32 olarak dağılır.
  • Üretilen dosyada birleştirme sürücüsü tanımsızken 50 birleştirmenin 43’ü çakışır ve elle çözüm 86 nesne yazar; merge=ours bu çakışmaların tümünü ortadan kaldırır.
  • Bin işlemede ayarsız tarihçe 5888, tam ayarlı tarihçe 5640 nesnedir; gereksiz 248 nesnenin oranı 0,0421’dir ve ölçek büyüdükçe azalmaz.

Sonraki Adım

Bu konunun dört dersi aynı depoya dört ayrı müdahale yaptı: bağımlı depoyu gömdü, ikili gövdeyi dışarı taşıdı, çalışma ağacını çoğalttı ve dönüşüm katmanını ayarladı. Dördü de tek bir soruyu varsaydı — deponun sınırının nerede olduğunu. Sonraki ders o varsayımı ölçer: aynı iş tek bir depoda ve dört ayrı depoda yapılırsa, klon bedeli ile arama adımı nasıl değişir, ve bileşenler arasında sorulan sorulardan kaçı ikinci düzende yanıtsız kalır?

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat