İçeriğe geç
academia.sh

Ders 16 / 26

Bağlam Sağlama

Aynı kurgu kod tabanında bağlamı büyütmekle bağlamı seçmenin yan yana ölçülmesi: bütün dosyaları göndermek beklenen kabulü 0,6921'e çıkarıyor ve 4224 belirteç ile 120 dosya harcıyor, yalnız gereken dosyaları göndermek 0,8233'e çıkarıyor ve 2274 belirteç ile 45 dosya harcıyor. İlgisiz her dosya beklenen kabulden 0,0400 götürüyor ve 624 belirteç ekliyor; eşiği yoktur, ilk dosyadan başlar. Bağlam sağlayıcının belirteç bedeli isabetinden bağımsızdır ve 2274'te sabittir, ama beklenen kabul 0,4960 ile 0,8233 arasında değişir; sağlayıcının bütün kod tabanını göndermeyi geçmesi için gereken dosyaları dört görevin yaklaşık üçünde bulması gerekir.

İçindekiler

Önceki ders bağlamı üç kez sabit verdi: hiç, hep aynı dosya, ya da hepsi. Uçlar arasındaki mesafe büyüktü — yirmi dört görevin yedisinden on sekizine — ama üçü de bir seçim değildi. Bir geliştirici masasında bağlam her görev için yeniden kurulur ve iki ayrı soru sorulur: hangi dosyalar ve kaç tane.

Bu ders o iki soruyu ayırır. Önce bağlam büyütülür: aynı dosya kümesi herkese verilir ve boyu bir bir artar. Sonra bağlam seçilir: her göreve yalnız o görevin gerektirdiği dosyalar gider. İki eğri belirteç ekseninde yan yana konur, ve üzerine üçüncü bir sayı eklenir: görevle ilgisi olmayan bir dosyanın kabule ne yaptığı.

  • YG9. Kod tabanı önceki derste gövdeleriyle kurulan aynı kurgu kod tabanıdır: beş modül, 53 satır. Burada yalnız yapısı gerekir, çünkü bağlam dosya adıyla seçilir.
  • YG10. Görev kümesi ve yardımcı benzeticisi de aynıdır: yirmi dört kurgu görev, üç sınıf, tohum 20260218, random yok.
  • YG11. Bağlamın kabule etkisi iki terimlidir: örtüşme (gereken dosyaların kaçı bağlamda) kabulü yükseltir, ilgisizlik (bağlamdaki dosyaların kaçı gereksiz) düşürür.
  • YG12. Bedel dosya başına düz 26 belirteçtir; dosya boyu bedele girmez. Gerçek bir bağlamda büyük dosya pahalıdır, yani buradaki bedel eğrisi iyimserdir.
  • YG13. Gönderilen dosya sayısı ayrıca sayılır; yirmi dört görev için toplamdır ve belirteçten bağımsız bir hacim ölçüsüdür.
  • YG14. Bağlam sağlayıcı kurgudur ve tek bir ayarı vardır: isabet, yani gereken kümeyi doğru bulduğu görev payı. Kaçırdığında bir gereken dosyayı düşürür, yerine ilgisiz bir dosya koyar; dosya sayısı değişmez, yalnız hangi dosya olduğu değişir.
  • YG15. Sağlayıcının kendi çekilişi tohumla sabittir; ikinci koşumda yalnız yardımcının belirsizliği değişir. Böylece iki koşum farkı seçime değil, yalnız modele yazılır.
  • YG16. Koşumdan bağımsız ölçü yine beklenen kabuldür; sayılan kabul iki tohumda ayrı basılır. Gecikme sınıfı bütün kurulumlarda tek çağrıdır, görev başına bir tane.

Kod Tabanının Yapısı ve Sağlayıcı

Bağlam seçimi için kod tabanının gövdeleri değil yapısı gerekir: hangi modül var, ne kadar uzun ve dışarıya hangi adları veriyor. Bir bağlam sağlayıcının çalıştığı düzlem de budur.

# AYNI KURGU KOD TABANI -- bes modul, 53 satir; govdeleri onceki derste kuruldu.
# Burada yalniz yapisi gerekiyor: boy ve disa verilen adlar.
BOY = {"okuma.py": 13, "tarife.py": 13, "denetim.py": 11, "ozet.py": 11, "bicim.py": 5}
DISA = {
    "okuma.py": ("ayristir", "tuketim"),
    "tarife.py": ("BASAMAK", "USTU", "bedel"),
    "denetim.py": ("GECERLI_BOLGE", "gecerli", "ayikla"),
    "ozet.py": ("bolge_toplam", "bolge_sayi"),
    "bicim.py": ("satir", "rapor"),
}
DOSYA = tuple(BOY)

TOHUM, M32 = 20260218, 0xFFFFFFFF


def uretec(t):
    x = ((t ^ (t >> 16)) * 2246822507) & M32
    x = ((x ^ (x >> 13)) * 3266489909) & M32
    s = [(x ^ (x >> 16)) & M32]

    def sonraki():
        s[0] = (s[0] * 1664525 + 1013904223) & M32
        return s[0] / 4294967296
    return sonraki


def izno(m):
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


SINIF = ("tamamlama", "aciklama", "donusturme")
GEREKEN = {
    0: ("okuma.py",),
    1: ("tarife.py",),
    2: ("denetim.py", "okuma.py"),
    3: ("ozet.py", "denetim.py"),
    4: ("bicim.py", "ozet.py"),
    5: ("tarife.py", "okuma.py"),
    6: ("ozet.py", "okuma.py", "tarife.py"),
    7: ("denetim.py", "bicim.py"),
}
GOREV = [                                   # 24 KURGU gorev: 3 sinif x 8
    {"ad": s + "-" + str(i + 1), "sinif": s, "gereken": GEREKEN[i], "zorluk": 0.05 * (i % 4)}
    for s in SINIF
    for i in range(8)
]
TABAN = {"tamamlama": 0.34, "aciklama": 0.72, "donusturme": 0.18}


def yardimci(gorev, baglam, tohum=TOHUM):   # BENZETICI -- KURGUDUR
    r = uretec(tohum ^ izno(gorev["ad"] + "|" + ",".join(sorted(baglam))))
    ortu = sum(1 for d in gorev["gereken"] if d in baglam) / len(gorev["gereken"])
    ilgisiz = sum(1 for d in baglam if d not in gorev["gereken"]) / len(DOSYA)
    puan = TABAN[gorev["sinif"]] + 0.55 * ortu - 0.30 * ilgisiz - gorev["zorluk"]
    puan = min(max(puan, 0.0), 1.0)
    kabul = r() < puan
    belirtec = 40 + 26 * len(baglam) + (18 if gorev["sinif"] == "donusturme" else 0)
    return {"kabul": kabul, "puan": puan, "belirtec": belirtec}


def saglayici(gorev, isabet, tohum=TOHUM):
    """KURGU baglam saglayici. Isabet ettiginde gereken kumeyi bulur; kacirdiginda
    bir gereken dosyayi dusurur ve yerine ilgisiz bir dosya koyar. Dosya sayisi ayni."""
    r = uretec(tohum ^ izno("saglayici|" + gorev["ad"]))
    if r() < isabet:
        return tuple(gorev["gereken"])
    ek = tuple(d for d in DOSYA if d not in gorev["gereken"])[:1]
    return tuple(gorev["gereken"][1:]) + ek


print("modul       satir  disa verilen")
for d in DOSYA:
    print(f"  {d:<10}{BOY[d]:>4}   {', '.join(DISA[d])}")
dagilim = {}
for g in GOREV:
    dagilim[len(g["gereken"])] = dagilim.get(len(g["gereken"]), 0) + 1
print(f"\ngorev {len(GOREV)}, gereken dosya sayisi dagilimi {dict(sorted(dagilim.items()))}"
      f", toplam gereken dosya {sum(len(g['gereken']) for g in GOREV)}")
print("ornek gorev:", GOREV[6]["ad"], "->", "+".join(GOREV[6]["gereken"]),
      " belirtec", yardimci(GOREV[6], GOREV[6]["gereken"])["belirtec"],
      "/ butun kod tabaniyla", yardimci(GOREV[6], DOSYA)["belirtec"])
modul       satir  disa verilen
  okuma.py    13   ayristir, tuketim
  tarife.py   13   BASAMAK, USTU, bedel
  denetim.py  11   GECERLI_BOLGE, gecerli, ayikla
  ozet.py     11   bolge_toplam, bolge_sayi
  bicim.py     5   satir, rapor

gorev 24, gereken dosya sayisi dagilimi {1: 6, 2: 15, 3: 3}, toplam gereken dosya 45
ornek gorev: tamamlama-7 -> ozet.py+okuma.py+tarife.py  belirtec 118 / butun kod tabaniyla 170

Görevlerin yarısından çoğu iki dosya istiyor, altısı bir, üçü üç. Yirmi dört görevin toplam ihtiyacı 45 dosyadır. Bütün kod tabanını her göreve göndermek ise 120 dosya demektir, yani gereğinin iki katından fazlası. Örnek görevde fark tek başına küçük görünüyor: 118 belirteçe karşı 170. Yirmi dört görev boyunca aynı fark birikir.

Büyütmek ile Seçmek

İki eğri aynı tabloda basılır. Toplu satırlar herkese aynı ilk k dosyayı verir; seçili satırlar her göreve yalnız kendi gereken dosyalarını verir ve üzerine sırayla ilgisiz dosya eklenir.

def olc(sec, tohum=TOHUM):
    kabul = bel = dosya = 0
    puan = 0.0
    for g in GOREV:
        b = sec(g)
        s = yardimci(g, b, tohum)
        kabul += s["kabul"]
        puan += s["puan"]
        bel += s["belirtec"]
        dosya += len(b)
    return kabul, puan / len(GOREV), bel, dosya


def yaz(ad, sec):
    a = olc(sec)
    kb = olc(sec, TOHUM + 1)[0]
    print(f"{ad:<26}{a[3]:>7}{a[1]:>11.4f}{a[0]:>8}/24{kb:>8}/24{a[2]:>10}")


print("kurulum                    dosya   beklenen  kabul A  kabul B  belirtec")
for k in range(6):
    yaz(f"toplu {k}", lambda g, b=DOSYA[:k]: b)
yaz("secili (yalniz gereken)", lambda g: g["gereken"])
for n in (1, 2, 3):
    def sec(g, n=n):
        ek = tuple(d for d in DOSYA if d not in g["gereken"])[:n]
        return tuple(g["gereken"]) + ek
    yaz(f"secili + {n} ilgisiz", sec)

print("\nsaglayici isabeti  bulunan gereken payi  beklenen  kabul A  kabul B  belirtec")
for isb in (0.00, 0.25, 0.50, 0.75, 1.00):
    def sec(g, i=isb):
        return saglayici(g, i)
    a = olc(sec)
    kb = olc(sec, TOHUM + 1)[0]
    bulunan = sum(sum(1 for d in g["gereken"] if d in sec(g)) for g in GOREV)
    print(f"{isb:>13.2f}{bulunan / 45:>22.4f}{a[1]:>10.4f}{a[0]:>8}/24{kb:>8}/24{a[2]:>10}")
kurulum                    dosya   beklenen  kabul A  kabul B  belirtec
toplu 0                         0     0.3383       7/24       7/24      1104
toplu 1                        24     0.4600      10/24       8/24      1728
toplu 2                        48     0.5402      12/24      13/24      2352
toplu 3                        72     0.6013      15/24      13/24      2976
toplu 4                        96     0.6608      15/24      15/24      3600
toplu 5                       120     0.6921      18/24      20/24      4224
secili (yalniz gereken)        45     0.8233      19/24      19/24      2274
secili + 1 ilgisiz             69     0.7833      19/24      18/24      2898
secili + 2 ilgisiz             93     0.7433      20/24      18/24      3522
secili + 3 ilgisiz            114     0.7029      17/24      20/24      4068

saglayici isabeti  bulunan gereken payi  beklenen  kabul A  kabul B  belirtec
         0.00                0.4667    0.4960      13/24      10/24      2274
         0.25                0.6222    0.5796      15/24      12/24      2274
         0.50                0.7333    0.6404      15/24      14/24      2274
         0.75                0.8222    0.7050      17/24      15/24      2274
         1.00                1.0000    0.8233      19/24      19/24      2274

Eğrinin Okunması

Toplu satırlar sezgiyi doğruluyor: dosya eklemek beklenen kabulü 0,3383’ten 0,6921’e çıkarıyor ve hiçbir adımda düşürmüyor. Bedel de düzgündür — her adım tam 624 belirteç, çünkü yirmi dört görevin her birine bir dosya daha giriyor. Eğri, bağlamı büyütmenin işe yaradığı iddiasının sayısıdır ve doğrudur.

Eğrinin bir zayıflığı var ve tabloda görünmüyor: sıra. Toplu satırlar dosyaları modül demetindeki sırayla ekliyor, yani ikinci satırın hangi dosyayı taşıdığı bir karar değil bir tesadüftür. Başka bir sırayla aynı iki uç nokta arasında başka bir eğri çıkardı. Seçili kurulumun böyle bir bağımlılığı yoktur, çünkü sıra sorusunu hiç sormaz. Bir kurulumun sayısı, listelenmemiş bir keyfî karara duyarlıysa o sayı tek başına okunmamalıdır.

İkinci zayıflık bedel tarafındadır ve seçimin lehinedir. Bu ölçümde her dosya boyundan bağımsız olarak 26 belirteç ediyor; oysa kod tabanının en uzun modülü en kısasının iki buçuk katından uzundur. Gerçek bir bağlamda toplu gönderim uzun dosyaların bedelini de öder, seçili gönderim çoğu zaman ödemez. Yani aşağıdaki fark bir alt sınırdır.

Seçili satır aynı iddiayı yerinden ediyor. Yalnız gereken dosyalar gönderildiğinde beklenen kabul 0,8233; bütün kod tabanının 0,6921’inden 0,1312 yüksek. Bunu 45 dosya ve 2274 belirteç ile yapıyor: dosya hacminin üçte birinden biraz fazlası, belirtecin yüzde elli dördü. İki eksende birden kazanan bir kurulum ender görülür ve buradaki nedeni açıktır: bütün kod tabanını göndermek gereken dosyaları da gönderir, ama yanında ortalama üç ilgisiz dosya taşır.

Aynı bedelde karşılaştırma bunu daha keskin yapıyor. Toplu 2 kurulumu 2352 belirteç harcayıp 0,5402 veriyor; seçili kurulum 2274 belirteçle, yani biraz daha azıyla, 0,8233. Neredeyse aynı bütçede 0,2831 fark. Belirteç bütçesi bir tasarım kısıtıysa, o bütçeyi nereye harcadığın ne kadar harcadığından daha çok belirliyor.

Sayılan kabul sütunları bir uyarı taşıyor. Seçili satır 19/24 ve bütün kod tabanı 18/24; aradaki fark tek görev. Ama ikinci koşumda sıralama tersine dönüyor: 19/24’e karşı 20/24. Sayılan kabulle bakıldığında bu iki kurulum ayırt edilemez, çünkü fark iki koşum farkının içinde kalıyor. Ayrımı yapan şey koşumdan bağımsız sütundur. Bu, kursun ölçü kuralının doğrudan uygulanmasıdır: iki koşumda oynayan bir sayı, tek koşumda okunduğunda karar verdirmez.

İlgisiz Dosyanın Eşiği Yoktur

Son üç seçili satır tek bir soruyu yanıtlıyor: doğru dosyalar zaten gönderildikten sonra fazladan bir dosya ne yapar. Yanıt düzgün ve tek yönlüdür. Beklenen kabul 0,8233’ten 0,7833’e, 0,7433’e ve 0,7029’a iniyor; her ilgisiz dosya tam 0,0400 götürüyor. Bedel aynı anda 2274’ten 4068’e çıkıyor, yine adım başına 624 belirteç.

Burada aranan “isabetin düştüğü nokta” bir eşik değildir: ilk ilgisiz dosyadan başlar. Bedava bir ilgisiz dosya yoktur, çünkü ilgisizlik terimi doğrusaldır ve örtüşme terimi zaten doyurulmuştur. Üç ilgisiz dosya eklemek belirteci yüzde yetmiş dokuz artırıp beklenen kabulden 0,1204 götürüyor — eklenen düzeneğin işi kötüleştirdiği en yalın satır budur.

Sayılan kabul burada da yanıltıcıdır ve niçin olduğu görülüyor: 19, 19, 20, 17 diye gidiyor, ikinci koşumda 19, 18, 18, 20. Tek koşuma bakan biri “iki ilgisiz dosya kabulü yükseltti” diyebilir. Beklenen kabul sütunu bu yorumu kapatıyor. Yirmi dört görevlik bir kümede tek bir kabulün ağırlığı 0,0417’dir, yani ilgisiz bir dosyanın gerçek etkisinden büyüktür; sayılan kabul bu ayrıntıyı gösterecek çözünürlükte değildir ve daha büyük bir görev kümesi gerektirir.

Sağlayıcının İsabeti Bedelden Bağımsızdır

İkinci tablo bağlam seçimini bir yeteneğe çeviriyor. Sağlayıcı her isabet düzeyinde aynı sayıda dosya gönderir, dolayısıyla belirteç sütunu beş satırda da 2274’tür. Değişen tek şey hangi dosyaların gönderildiğidir, ve beklenen kabul 0,4960 ile 0,8233 arasında oynuyor. Bağlam kalitesi burada belirteçle satın alınmıyor; ölçülen fark tamamen seçimin kendisinden geliyor.

Bu tablonun son satırı, bir önceki tablonun seçili satırıyla aynıdır ve aynı olması gerekir: 1,00 isabet, gereken kümeyi her görevde bilen bir sağlayıcıdır. Böyle bir sağlayıcı bir ölçüm kurgusudur, bir kurulum değil. Hangi dosyaların gerektiğini bilmek, görevin çözülmüş olmasına çok yakın bir bilgidir; gerçek bir sağlayıcı bunu ad benzerliği, çağrı ilişkisi ya da geçmiş değişikliklerden tahmin eder. Bu yüzden 0,8233 bir hedef değil bir üst sınırdır, ve tablo o sınıra ne kadar yaklaşıldığının bedelini değil, yaklaşamamanın bedelini gösterir.

Sıfır isabette bile bulunan gereken dosya payı 0,4667’dir, çünkü iki dosyalık bir görevden biri düşürüldüğünde öbürü yerinde kalır. Yani kötü bir sağlayıcı sıfır değildir, sadece zayıftır — ve 0,4960 beklenen kabul, hiç bağlam göndermemenin (0,3383) üzerindedir.

Asıl karar noktası ortadadır. Bütün kod tabanını göndermek 0,6921 veriyor. Sağlayıcı bunu 0,50 isabette geçemiyor (0,6404), 0,75 isabette geçiyor (0,7050). Yani bir bağlam sağlayıcısı, gereken dosyaları dört görevin yaklaşık üçünde bulabiliyorsa her şeyi göndermekten iyidir; bulamıyorsa daha kötüdür ve üstelik bunu ucuz olduğu için fark etmek zordur. Bedel sütunu sabit olduğu için sağlayıcının kötülüğü faturada görünmez, yalnız kabulde görünür.

Özet

  • Bağlamı büyütmek beklenen kabulü 0,3383’ten 0,6921’e çıkarır ve her adım tam 624 belirteç eder; eğri düzgündür ve hiçbir adımda düşmez.
  • Bağlamı seçmek aynı görev kümesinde 0,8233 verir; bunu 45 dosya ve 2274 belirteçle yapar, yani bütün kod tabanından hem 0,1312 yüksek hem yaklaşık yarı bedelde.
  • Neredeyse eşit bütçede fark daha da büyüktür: toplu iki dosya 2352 belirteçle 0,5402, seçili bağlam 2274 belirteçle 0,8233.
  • İlgisiz her dosya beklenen kabulden tam 0,0400 götürür ve 624 belirteç ekler; eşiği yoktur, ilk dosyadan başlar ve üç dosyada 0,1204 kayıp eder.
  • Sayılan kabul bu kararların ikisinde de ayrım yapmaz (19/24’e karşı 18/24, ikinci koşumda tersine döner); ayrımı koşumdan bağımsız beklenen kabul sütunu yapar.
  • Bağlam sağlayıcının belirteç bedeli isabetinden bağımsızdır ve 2274’te sabittir; bütün kod tabanını göndermeyi geçmesi için gereken dosyaları dört görevin yaklaşık üçünde bulması gerekir.

Sonraki Adım

Bu iki derste her görev tek bir çağrıydı: bağlam gitti, öneri geldi, geliştirici kabul etti ya da etmedi. Karar noktası tekti ve hemen oradaydı. Bir geliştirme işi çoğu zaman böyle durmaz — bir dosyayı okumak, bir işlevi değiştirmek, çağıranları güncellemek ve raporu yeniden biçimlemek tek bir istekle devredildiğinde ortaya çok adımlı bir iş çıkar ve geliştirici artık her adımda değil, durduğu yerde bakar. Sonraki ders bu durma yerini ölçer: kaç adımda bir durulduğunda bir hata yayılmadan yakalanıyor, kaç adım boşa gidiyor ve durmanın kendisi kaç çağrıya mal oluyor.

İ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