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,
randomyok. - 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.