İçeriğe geç
academia.sh

Ders 09 / 12

Büyük Dosya Depolama

Tarihçeyi ağırlaştıran işleme sayısı değil nesne türüdür: bin işlemenin onda birinden azı olan 91 ikili işleme toplam nesnenin 0,6777'sini üretir, klon 5640 nesnedir ve ikilisiz 1818'e iner.

İçindekiler

Önceki derste nesne sayısı işleme sayısını izliyordu: üç yüz işlemelik alt modül, seksen işlemelik olandan yaklaşık beş kat fazla nesne getirdi. Oran neredeyse birebirdi çünkü her işleme aynı ağırlıkta bir kayıt bırakıyordu.

Bu ders sezginin bozulduğu duruma bakar. Aynı tarihçede işlemelerin küçük bir azınlığı nesnelerin çoğunluğunu üretebilir ve o zaman “tarihçe ne kadar büyük?” sorusunun işleme sayısıyla verilen yanıtı yanlış olur. Sorumuz şudur: bir tarihçeyi ağırlaştıran şey kaç işleme yazıldığı mıdır, yoksa o işlemelerin ne tür nesne ürettiği midir? Depolama maliyetinin kendisi burada tartışılmıyor — o eksen İlişkisel Veritabanı Yönetimi ve Bulutta Depolama ve Veri kurslarında kuruldu. Burada ölçülen tek şey tarihçedeki nesne payıdır.

İkili Varlık Neden Ayrı Bir Sınıf

Sürüm kontrolü metin dosyalarını fark olarak saklayabilir: iki sürüm arasındaki değişen satırlar, dosyanın tamamından çok daha küçüktür. Bu, bir dosyanın yüz sürümünün yüz kopya etmemesini sağlar.

İkili varlıklarda bu düzenek çalışmaz. Bir görsel, bir ses kaydı ya da derlenmiş bir çıktı sıkıştırılmış bir bayt dizisidir; içeriğinde tek bir alan değiştiğinde bayt dizisinin tamamı değişir. Satır diye bir yapı yoktur, dolayısıyla satır farkı da yoktur. Sonuç şudur: ikili varlığın her sürümü tarihçede yeni ve tam bir nesnedir. Ortak kurgu bunu doğrudan modelliyor — ikili varlık taşıyan bir işleme, metin işlemesinin 2 nesnesine karşılık 42 nesne yazıyor.

Bu birikimin geri alınamaz bir yanı var. Bir ikili varlık bir kez işlendiğinde tarihçeye girer ve sonraki bir işlemede silinmesi onu tarihçeden çıkarmaz; yalnız çalışma ağacından çıkarır. Klonlayan herkes o nesneyi almaya devam eder, çünkü klon çalışma ağacını değil tarihçeyi getirir.

İşaretçi Düzeni

Büyük dosya depolama (large file storage), ikili gövdeyi tarihçenin dışına taşıyan bir süzgeç düzenidir. Depo özniteliklerinde bir dosya deseni bir süzgeç adına bağlanır; süzgeç iki yönlü çalışır. Temizleme süzgeci (clean filter) dosya işlenirken devreye girer, gövdeyi ayrı bir depoya yazar ve tarihçeye gövdenin yerine küçük bir işaretçi dosyası koyar. Açma süzgeci (smudge filter) dosya çalışma ağacına yazılırken devreye girer, işaretçiyi okur ve gövdeyi ayrı depodan getirir.

# öznitelik dosyası ve işaretçi içeriği — örnek döküm, çalıştırılmamıştır

# .gitattributes
*.bin  filter=buyuk-dosya -text
*.png  filter=buyuk-dosya -text

# tarihçeye giren işaretçi dosyası (gövde değil)
surum https://<süzgeç-belirtimi>/v1
ozet  sha256:<gövdenin özeti>
boyut 41943040

Tarihçede duran şey bu üç satırlık metindir. -text niteliği dosyayı ikili olarak işaretler ve satır sonu dönüşümünün ona uygulanmasını engeller — o ayrım bu konunun dördüncü dersinde ölçülüyor. Süzgecin adı bir ürün adı değil, yapılandırmada tanımlanan bir addır; aynı desen başka bir süzgece de bağlanabilir.

Düzenin tek gerçek kazancı şudur: klon artık her sürümü değil, yalnız işaretçileri getirir. Gövde, çalışma ağacına gerçekten yazılacak sürüm için ve yalnız o sürüm için istenir.

Ölçümün Varsayımları

  • BD7 — Ölçüm ortak kurgunun dört ölçeğini olduğu gibi kullanır: 50, 200, 1000, 4000 işleme. İkili varlık taşıyan işlemeler kurgunun kendi dağılımından gelir; seçilmez.
  • BD8 — Metin işlemesi 2 nesne yazar (ağaç ve damla). İkili varlık taşıyan işleme bunlara 40 nesne ekler; bu, gövdenin o sürümünün tarihçedeki karşılığıdır.
  • BD9 — İşaretçi düzeninde ikili gövde tarihçenin dışına çıkar ve yerine 1 nesnelik işaretçi damlası kalır; ikili işleme 3 nesne yazar.
  • BD10 — “Ayrı depo” ölçümün dışındadır. Sayılan tek şey tarihçedeki nesne; gövdelerin dışarıda ne kadar yer kapladığı bu ölçünün konusu değildir.
  • BD11 — Klondan sonra çalışabilmek için tek bir ikili sürümün gövdesi gerekir; ölçüm bunu 40 nesne olarak klonun üstüne ekler.
  • BD12 — “İkilisiz” sütunu, ikili varlık taşıyan işlemelerin hiç yazılmamış olduğu durumu verir; bu bir temizlik sonucu değil, karşılaştırma tabanıdır.
  • BD13 — Bedel dokunulan nesne birimiyle sayılır. Bayt, disk ve ağ süresi ölçümün dışındadır.

Ölçüm

"""Buyuk dosya depolama: agirligi uretenin isleme sayisi mi nesne turu mu.

Bolum 1 - dort olcekte ikili isleme payi ve nesne payi.
Bolum 2 - ayni tarihce isaretci duzeniyle: klon nesnesi nereye iniyor.
"""
TOHUM = 20260814
DOSYALAR = ("olcum.py", "rapor.py", "kimlik.py", "ayar.py", "belge.md")
OLCEKLER = (50, 200, 1000, 4000)
ISARETCI = 1        # isaretci damlasi: ikili govdenin yerine gecen tek nesne
IKILI_GOVDE = 40    # ortak kurguda bir ikili surumun nesnesi


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 isaretci_bedeli(t):
    """Ikili govde disariya tasinir; tarihcede tek isaretci damlasi kalir."""
    return sum(2 + (ISARETCI if x["ikili"] else 0) for x in t)


def calisan_kopya(t):
    """Klondan sonra calismak icin gereken tek ikili surum."""
    return IKILI_GOVDE if any(x["ikili"] for x in t) else 0


print("isleme  ikili isleme  ikili payi  klon nesnesi  ikilisiz  ikili nesne  nesne payi")
for n in OLCEKLER:
    t = tarihce(n)
    ikili = sum(1 for x in t if x["ikili"])
    tam, dus = klon_bedeli(t), klon_bedeli(t, False)
    print(f"{n:6d} {ikili:13d} {ikili / n:11.4f} {tam:13d} {dus:9d} "
          f"{tam - dus:12d} {(tam - dus) / tam:11.4f}")
print()
print("isleme  tarihcede klon  isaretci duzeni  + tek surum  kazanilan nesne   kat")
for n in OLCEKLER:
    t = tarihce(n)
    tam, isaretci = klon_bedeli(t), isaretci_bedeli(t)
    calisir = isaretci + calisan_kopya(t)
    print(f"{n:6d} {tam:15d} {isaretci:16d} {calisir:12d} {tam - calisir:16d} "
          f"{tam / calisir:5.2f}")
print()
n = 1000
t = tarihce(n)
ikili = sum(1 for x in t if x["ikili"])
tam, dus = klon_bedeli(t), klon_bedeli(t, False)
print(f"tarihce {n} isleme, ikili varlik tasiyan {ikili}, toplam nesne {tam}, "
      f"ikili payi {(tam - dus) / tam:.4f}")
print(f"metin islemesi {n - ikili} silinse kazanilan nesne {dus}; "
      f"ikili isleme {ikili} silinse kazanilan nesne {tam - dus}")
isleme  ikili isleme  ikili payi  klon nesnesi  ikilisiz  ikili nesne  nesne payi
    50             7      0.1400           380        86          294      0.7737
   200            13      0.0650           920       374          546      0.5935
  1000            91      0.0910          5640      1818         3822      0.6777
  4000           365      0.0912         22600      7270        15330      0.6783

isleme  tarihcede klon  isaretci duzeni  + tek surum  kazanilan nesne   kat
    50             380              107          147              233  2.59
   200             920              413          453              467  2.03
  1000            5640             2091         2131             3509  2.65
  4000           22600             8365         8405            14195  2.69

tarihce 1000 isleme, ikili varlik tasiyan 91, toplam nesne 5640, ikili payi 0.6777
metin islemesi 909 silinse kazanilan nesne 1818; ikili isleme 91 silinse kazanilan nesne 3822

Nesne Sayısı İşleme Sayısını İzlemez

Üçüncü satır kursun dördüncü okumasını ödüyor. Bin işlemelik tarihçede ikili varlık taşıyan işleme sayısı 91’dir — işlemelerin 0,0910’u, yani onda birinden azı. Aynı 91 işleme toplam nesnenin 0,6777’sini üretiyor. Kalan 909 işleme, yani tarihçenin dokuzda dokuza yakını, nesnelerin yalnız üçte birini yazıyor.

Son satır bunu bir düşünce deneyiyle keskinleştiriyor. Dokuz yüz dokuz metin işlemesinin tümü silinseydi tarihçeden 1818 nesne düşerdi. Doksan bir ikili işleme silinseydi 3822 nesne düşerdi — iki katından fazlası, onda birinden az işlemeyle. Tarihçeyi ağırlaştıran şey işleme sayısı değil, nesne türüdür. Bu, konunun ilk dersindeki durumun tam tersidir: orada bedeli belirleyen tarihçenin boyuydu, burada bileşimi.

Üst tablo bir uyarı da taşıyor. Nesne payı dört ölçekte 0,7737, 0,5935, 0,6777 ve 0,6783 çıkıyor; sıralı bir eğilim yok. Nedeni sağdaki değil soldaki sütunda: elli işlemelik tarihçede ikili işleme sayısı 7’dir ve bu ölçekte ölçülebilen en küçük fark 1/50 = 0,0200’dür. Tek bir işlemenin yer değiştirmesi payı iki puan oynatır. Bin ve dört bin işlemede pay 0,6777 ile 0,6783 arasında oturuyor; asıl değer budur ve küçük ölçekteki dağılım ondan bir sonuç çıkarmaya elverişli değildir.

İşaretçi Düzeninin Ödediği

Alt tablonun birimi yine dokunulan nesnedir. Bin işlemelik tarihçede klon 5640 nesneden 2091 nesneye iniyor; çalışmak için gereken tek ikili sürüm eklenince 2131. Kazanılan nesne 3509, kat 2,65. Dört bin işlemede kazanç 14195 nesneye çıkıyor ve kat 2,69’da kalıyor — düzenin kazancı ölçekle birlikte büyüyor ama oranı sabitleniyor, çünkü kazanç doğrudan ikili işleme payına bağlı.

İki yüz işlemelik satır kattan düşük çıkıyor: 2,03. Nedeni üst tabloda yazılı — o ölçekte ikili işleme payı 0,0650 ile en düşük değerinde. Kat, doğrudan bu payın işlevidir ve bağımsız bir ölçüt değildir. Aynı düzen, ikili varlık hiç taşımayan bir depoda hiçbir şey kazandırmaz; kazandığını sandıran her sayı, aslında o deponun ikili payını ölçmektedir.

Kazancın nereden gelmediğine dikkat etmek gerekir. İşaretçi düzeni hiçbir işlemeyi kaldırmıyor; tarihçe hâlâ bin işleme. Kaldırdığı şey her ikili sürümün gövdesidir ve bu gövdeler yok olmuyor, yalnız tarihçenin dışına, ayrı bir depoya taşınıyor. Düzenin bedeli de oradadır: klonlayan taraf artık iki kaynağa birden erişmek zorundadır ve ikinci kaynağa erişemezse tarihçesi eksiksiz olduğu hâlde çalışma ağacını kuramaz. Alt modülde ölçülen bağımlılığın bir başka biçimidir bu — orada eksik olan bir tarihçeydi, burada bir gövde deposu.

Ölçünün görmediği bir eksen de var ve adının konması gerekir. Nesne birimi bir gövdenin kaç bayt olduğunu sormaz; kurguda bir ikili sürüm 40 nesnedir ve bu sayı gövdenin büyüklüğünden bağımsızdır. Gerçek bir depoda büyük bir gövde ile küçük bir gövde aynı nesne sayısını üretir ama aynı bedeli ödetmez. Bu ders nesne payını ölçüyor; bayt ekseni ölçünün dışındadır ve tablodan bir disk sonucu çıkarılamaz.

İkinci bir sınır: düzen ancak baştan kurulduğunda tam kazanç verir. Süzgeç bugün tanımlanırsa bugünden sonraki işlemelerin gövdeleri dışarı çıkar; tarihçede zaten duran 3822 nesne yerinde kalır ve her klon onları getirmeye devam eder.

İkilinin Birleştirilememesi

Nesne sayısının yanında ikinci bir sonuç daha var ve o tarihçede değil, çalışmada ödeniyor. İki dal aynı ikili varlığın ayrı sürümlerini yazdığında birleştirme çakışması doğar ve çakışma çözülemez: birleştirme, iki metnin satırlarını harmanlayarak çalışır, ikili gövdede harmanlanacak satır yoktur. Elde kalan tek karar, iki sürümden birini seçmektir.

Bu yüzden ikili desenlere -merge niteliği de verilir; öznitelik, aracın harmanlamayı denemesini engeller ve doğrudan seçim ister. -diff niteliği aynı gerekçenin görüntüleme tarafıdır: iki ikili gövdeyi satır satır karşılaştırmanın anlamı yoktur, çıktı okunmaz olur. Bu iki niteliğin ayarlanmadığı durumda ne kadar gereksiz iş doğduğu konunun dördüncü dersinde ölçülüyor.

Klonun Kendisini Daraltmak

İşaretçi düzeni nesneyi tarihçenin dışına taşır. Aynı bedele başka bir açıdan giren iki düzenek daha vardır ve ikisi de nesneyi yerinde bırakıp ne zaman getirileceğini değiştirir.

# öğretilen komutlar — örnek döküm, çalıştırılmamıştır

git clone --filter=blob:none <depo-adresi>
git clone --depth 1 <depo-adresi>
git sparse-checkout set bilesenler/olcum-cekirdegi

Kısmi klon damlaları klon anında getirmez; işleme ve ağaç nesneleri gelir, damlalar ancak bir dosya gerçekten okunduğunda istenir. Sığ klon tarihçeyi belirli bir derinlikte keser ve daha eski işlemeleri hiç getirmez. Seyrek çıkarma ise nesne deposuna değil çalışma ağacına bakar: tarihçe eksiksiz gelir, çalışma ağacına yalnız seçilen yollar yazılır.

Üçünün de ortak yanı bir erteleme olmalarıdır: nesne hâlâ tarihçededir ve gerektiğinde istenir. İşaretçi düzeni bundan farklıdır, gövdeyi tarihçeden çıkarır. Bu ders ikincisini ölçüyor; ilk üçü aynı birimle ölçülebilir ama başka bir kurgu ister, çünkü kazançları depoya değil erişim örüntüsüne bağlıdır. Sığ klonun ayrı bir sınırı da vardır: kesilen tarihçe üzerinde ikili arama ve suçlama, kesilen aralığı hiç göremez.

Geriye Dönük Temizlik ve Kurtarma

Var olan bir tarihçeden ikili gövdeleri çıkarmak yalnız bir yolla olur: tarihçeyi yeniden yazarak. Bu, konunun birinci dersinde ölçülen işlemdir ve kuralları burada da geçerlidir.

İşlem her ikili işlemenin ve ondan sonraki her işlemenin kimliğini değiştirir; bin işlemelik tarihçede ilk ikili işleme erken bir noktadaysa neredeyse bütün kimlikler değişir. Geri alınamaz: eski kimlikler artık hiçbir şeyi göstermez, o kimliklere dayanan her etiket, her sabitlenmiş sürüm ve her dış atıf kopar. Depoyu klonlamış her kopya yeniden klonlamak zorundadır; eski kopyadan itilen tek bir dal, silinen gövdeleri geri getirir ve işlem baştan yapılır. Komutun tam biçimi burada verilmiyor, çünkü yanlış aralıkla çalıştırıldığında kaybı bildiren bir uyarı yoktur.

Kurtarma yolları önceden kurulur, sonradan değil. Birincisi: işlem çalıştırılmadan önce deponun eksiksiz bir kopyası ayrı bir yerde tutulur; bu kopya yeni tarihçeyle eşitlenmediği sürece eski kimliklerin tek kaynağıdır. İkincisi: dönüşüm önce bu ayrı kopyada denenir ve sonuç sayılır — kaç işlemenin kimliği değişti, kaç nesne düştü. Üçüncüsü: yerelde yanlış giden bir dönüşümden sonra referans günlüğü, çöp toplama penceresi kapanmadan eski uçları geri verir. Pencere kapandığında bu yol da kapanır. Dördüncüsü ve en ucuzu: deseni öznitelik dosyasına deponun ilk gününde yazmak. Kazanç tabloda okunuyor; bedeli, yalnızca baştan kurulduğunda ödenmemiş olması.

Özet

  • İkili varlık satır farkına elverişli değildir; her sürümü tarihçede yeni ve tam bir nesne olarak birikir ve bir kez işlendikten sonra silinmesi onu tarihçeden çıkarmaz.
  • Bin işlemelik tarihçede ikili varlık taşıyan 91 işleme vardır — işlemelerin 0,0910’u — ve toplam nesnenin 0,6777’sini üretir; klon 5640 nesne, ikilisiz 1818’dir.
  • 909 metin işlemesi silinse 1818 nesne düşer, 91 ikili işleme silinse 3822: tarihçeyi ağırlaştıran işleme sayısı değil, nesne türüdür.
  • İşaretçi düzeni bin işlemede klonu 5640’tan 2131 nesneye indirir (2,65 kat) ama hiçbir işlemeyi kaldırmaz; gövdeler ayrı bir depoya taşınır ve ikinci bir erişim koşulu doğar.
  • Geriye dönük temizlik tarihçeyi yeniden yazar, geri alınamaz ve her kopyanın yeniden klonlanmasını gerektirir; güvenli yol, ayrı bir kopyada denemek ve deseni deponun ilk gününde yazmaktır.

Sonraki Adım

İşaretçi düzeni klon bedelini üçte bire indirdi ama tabloda hâlâ klon yazıyor: bedel her seferinde yeniden ödeniyor. Aynı depoda iki dal üzerinde birlikte çalışmak gerektiğinde alışılmış çözüm ikinci bir klondur ve o klon nesnelerin tamamını yeniden kopyalar. Sonraki ders bu varsayımı sorgular: aynı deponun nesne deposunu paylaşan ikinci bir çalışma alanı kurulabilir mi, ve kurulursa dal başına klonla karşılaştırıldığında kaç nesne kopyalanmamış olur?

İ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