Ders 16 / 22
Bellek Eskitme
Eskitme eşiğinin yedi ayarda süpürülmesi: eşiksiz bellekte okumaların 0,4528'i bayat ve başarım 0,6389. Eşik sıkıldıkça bayat pay 0,0000'a iniyor, başarım 0,9306'ya çıkıyor, ama düşürülen kayıtların hâlâ geçerli olan payı 0,0000'dan 0,9701'e tırmanıyor ve adım 138'den 315'e çıkıyor. Eşiği sekizin altına sıkmanın kazandırdığı başarım iki koşum farkının kendisi kadar kalıyor, yani ölçülmemiş sayılır.
İçindekiler
Önceki iki ders belleği iki yönden ele aldı: görevler arasında neyin yazılacağı, görev içinde neyin taşınacağı. İkisinde de kayıtların doğru olduğu varsayıldı. Oysa ölçüm ağı hareket eder: bir sayaç yeni dönemde yeniden okunur, endeks farkı başka bir sayıya döner, bedel değişir. Bellekteki kayıt yerinde durur ve hiçbir hata vermeden yanlışa döner.
Bunun çaresi bir alan düşürmesi değildir; sorun yerin darlığı değil kaydın yaşıdır. Eskitme (memory expiry) kayda bir yaş sınırı koyar: sınırı geçen kayıt düşürülür. Bu ders o sınırı süpürür ve iki sayıyı yan yana basar. Eşik sıkılaştıkça bayat kayıt payı düşer, ama düşürülen kayıtların hâlâ geçerli olan payı büyür — ikisi aynı ayarla zıt yönlere gider.
- AB74. Kod bir benzeticidir; gerçek bir bellek servisi ya da araç sunucusu çağrılmaz. Ortam, araçlar ve görevler kurgudur, tohum 20260218.
- AB75. Ortam hareket eder: her altı görevde bir, on iki abone yeni bir dönem okuması alır (önceki endeks şimdikinin yerini alır). Belge dağarcığı değişmez.
- AB76. Bellek seçici politikayla yazılır: plana giren gözlemler tek kayıtta birleşir, kayıt abone koduyla (belge kayıtları soru metniyle) anahtarlanır ve yazıldığı görev sırasını taşır.
- AB77. Eskitme eşiği, kaydın taşıyabileceği en büyük yaştır; yaşı eşikten büyük kayıt her görevin başında düşürülür.
- AB78. Bayat kayıt, alanları ortamın o andaki değeriyle örtüşmeyen kayıttır; bayat pay okuma başına sayılır.
- AB79. Kayıp kayıt, eşiğin düşürdüğü ama düşürüldüğü anda hâlâ geçerli olan kayıttır; kayıp pay düşürülen kayıt başına sayılır.
- AB80. Akış 72 görev, adım bütçesi 8; taban çizgisi eşiksiz bellektir.
Kayıt Yerinde Durur, Değer Değişir
Aşağıdaki blok ortak tanımı kurar ve tek bir abonede bayatlamayı gösterir.
# KURGU ortam ve KURGU ajan. Gercek bir model ucu, arac sunucusu ya da bellek # servisi cagrilmaz. Abone kayitlari, belgeler ve gorevler kurgudur, tohum 20260218. 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 ayrik(u, w): t = 0.0 for i, x in enumerate(w): t += x if u < t: return i return len(w) - 1 def belirtecle(m): b = [] for s in str(m).lower().replace(",", " , ").split(): while len(s) > 5: b.append(s[:5]) s = s[5:] b.append(s) return b def izno(m): h = 2166136261 for c in str(m): h = ((h ^ ord(c)) * 16777619) & M32 return h BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"] TIP = ["mesken", "isyeri"] ABONE = {} for i in range(60): r = uretec(TOHUM + 31 * i) onceki = 10000 + int(r() * 80000) ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)], "onceki": onceki, "simdiki": onceki + int(r() * 70)} BASAMAK, USTU = ((10, 4), (25, 7), (40, 11)), 16 ISYERI_KAT = 2 BELGE = {"TR01": "tarife basamaklari 10 25 40 metrekup ve ustu", "TR02": "isyeri abonesinde birim ucret iki katidir", "SY01": "endeks farki tuketimi verir sayac donusu 100000 eklenir", "AR01": "ariza kaydi acildiginda saha ekibi iki gun icinde gider", "KS01": "planli kesinti duyurusu bir hafta once yayimlanir"} CAGRI = [0] # arac cagri sayaci def _bedel(m3, tip): kalan, alt, top = m3, 0, 0 for ust, birim in BASAMAK: dilim = min(kalan, ust - alt) if dilim <= 0: break top += dilim * birim kalan -= dilim alt = ust top += kalan * USTU return top * (ISYERI_KAT if tip == "isyeri" else 1) def t_sayac_oku(abone=None, **_): a = ABONE.get(abone) if a is None: return {"hata": "abone yok"} return {"onceki": a["onceki"], "simdiki": a["simdiki"], "tip": a["tip"], "bolge": a["bolge"]} def t_tuketim(onceki=None, simdiki=None, **_): if onceki is None or simdiki is None: return {"hata": "eksik alan"} f = simdiki - onceki return {"m3": f + 100000 if f < 0 else f} def t_tarife(m3=None, tip="mesken", **_): if m3 is None: return {"hata": "eksik alan"} return {"tutar": _bedel(m3, tip)} def t_belge(anahtar=None, **_): if not anahtar: return {"hata": "eksik alan"} ab = set(belirtecle(anahtar)) en, kod = -1, None for k, m in BELGE.items(): o = len(ab & set(belirtecle(m))) if o > en: en, kod = o, k return {"kod": kod, "metin": BELGE[kod]} if en > 0 else {"hata": "bulunamadi"} def t_kayit(abone=None, sutun=None, deger=None, **_): if not (abone and sutun and deger is not None): return {"hata": "eksik alan"} return {"yazildi": True, "abone": abone, "sutun": sutun, "deger": deger} ARAC = { "sayac_oku": {"islev": t_sayac_oku, "alan": ("abone",), "yan_etki": False}, "tuketim": {"islev": t_tuketim, "alan": ("onceki", "simdiki"), "yan_etki": False}, "tarife": {"islev": t_tarife, "alan": ("m3", "tip"), "yan_etki": False}, "belge_ara": {"islev": t_belge, "alan": ("anahtar",), "yan_etki": False}, "kayit_yaz": {"islev": t_kayit, "alan": ("abone", "sutun", "deger"), "yan_etki": True}, } ARAC_ADI = list(ARAC) def cagir_arac(ad, durum): """Sema disindaki alanlar suzulur; eksik alan aracin kendi hatasidir.""" CAGRI[0] += 1 if ad not in ARAC: return {"hata": "arac yok"} kw = {a: durum[a] for a in ARAC[ad]["alan"] if a in durum} return ARAC[ad]["islev"](**kw) GOREV = [] for i in range(24): r = uretec(TOHUM + 9973 * i) ab = f"A{1 + int(r() * 60):03d}" t = ayrik(r(), [0.30, 0.22, 0.20, 0.28]) if t == 0: GOREV.append({"ad": f"G{i + 1:02d}", "tur": "bedel", "abone": ab, "istek": f"{ab} abonesinin bu donem bedeli nedir", "dizi": ("sayac_oku", "tuketim", "tarife")}) elif t == 1: GOREV.append({"ad": f"G{i + 1:02d}", "tur": "tuketim", "abone": ab, "istek": f"{ab} abonesinin bu donem tuketimi kac metrekup", "dizi": ("sayac_oku", "tuketim")}) elif t == 2: GOREV.append({"ad": f"G{i + 1:02d}", "tur": "belge", "abone": ab, "istek": "sayac donusunde endeks farki nasil hesaplanir", "dizi": ("belge_ara",)}) else: GOREV.append({"ad": f"G{i + 1:02d}", "tur": "kayit", "abone": ab, "istek": f"{ab} abonesinin bedelini hesapla ve kayda yaz", "dizi": ("sayac_oku", "tuketim", "tarife", "kayit_yaz")}) def dogru_yanit(g): a = ABONE[g["abone"]] f = a["simdiki"] - a["onceki"] m3 = f + 100000 if f < 0 else f if g["tur"] == "tuketim": return m3 if g["tur"] == "belge": return "SY01" return _bedel(m3, a["tip"]) def gorme(d): return max(0.34, 0.80 - 0.09 * (d - 1)) # dogru araci secme payi, derinlikle duser def ajan(g, en_cok_adim=8, tohum=TOHUM, oz_elestiri=False, onay=False): """KURGU ajan dongusu. Gercek bir model cagrilmaz; arac secimi gorevin dizisine ve derinlige bagli tek bir cekilisten gelir.""" r = uretec(tohum ^ izno(g["ad"])) alan = {"abone": g["abone"], "anahtar": g["istek"], "sutun": "bedel"} iz, adim, bel, hata = [], 0, 0, 0 dizi, k = g["dizi"], 0 while adim < en_cok_adim: adim += 1 bel += 60 + 22 * len(iz) hedef = dizi[k] if k < len(dizi) else None if hedef is None: # is bitti , ajan durmali if r() < 0.88: return {"bitti": True, "adim": adim, "iz": iz, "belirtec": bel, "hata": hata, "yanit": alan.get("sonuc"), "onay": alan.get("onay", 0)} sec = ARAC_ADI[int(r() * len(ARAC_ADI))] else: sec = hedef if r() < gorme(k + 1) else ARAC_ADI[int(r() * len(ARAC_ADI))] if ARAC[sec]["yan_etki"] and onay: alan["onay"] = alan.get("onay", 0) + 1 if sec == "kayit_yaz": alan["deger"] = alan.get("sonuc") s = cagir_arac(sec, alan) iz.append((sec, "hata" in s)) bel += 30 if "hata" in s: hata += 1 if oz_elestiri: bel += 40 continue alan.update({kk: vv for kk, vv in s.items() if kk != "hata"}) if sec == "tuketim": alan["sonuc"] = s["m3"] if sec == "tarife": alan["sonuc"] = s["tutar"] if sec == "belge_ara": alan["sonuc"] = s["kod"] if sec == hedef: k += 1 return {"bitti": False, "adim": adim, "iz": iz, "belirtec": bel, "hata": hata, "yanit": alan.get("sonuc"), "onay": alan.get("onay", 0)} ab = "A026" eski = dict(ABONE[ab]) kayit = t_sayac_oku(abone=ab) ABONE[ab]["onceki"] = ABONE[ab]["simdiki"] ABONE[ab]["simdiki"] += 31 # yeni donem okumasi print("bellekteki kayit:", kayit["onceki"], kayit["simdiki"], "-> tuketim", t_tuketim(onceki=kayit["onceki"], simdiki=kayit["simdiki"])["m3"]) print("ortamdaki deger :", ABONE[ab]["onceki"], ABONE[ab]["simdiki"], "-> tuketim", t_tuketim(onceki=ABONE[ab]["onceki"], simdiki=ABONE[ab]["simdiki"])["m3"]) ABONE[ab].update(eski)
bellekteki kayit: 88422 88477 -> tuketim 55 ortamdaki deger : 88477 88508 -> tuketim 31
Kayıt değişmedi, ortam değişti. Bellekten dönen endeks çifti 55 metreküp veriyor, sayacın o andaki değeri 31. Ajan hata almaz, araç hata döndürmez, döngü kısalır ve yanıt yanlıştır: bayat bir kayıt doğru kayıttan ayırt edilemez.
Eşiği Sıkmak
Aşağıdaki blok akışı, dönem yenilemelerini ve eşik süpürmesini kurar.
# ---- Eskitme: kaydin yasi ile gecerliligi PLAN = {"bedel": (("sayac_oku", "tuketim", "tarife"), "{a} abonesinin bu donem bedeli nedir"), "tuketim": (("sayac_oku", "tuketim"), "{a} abonesinin bu donem tuketimi kac metrekup"), "belge": (("belge_ara",), "sayac donusunde endeks farki nasil hesaplanir"), "kayit": (("sayac_oku", "tuketim", "tarife", "kayit_yaz"), "{a} abonesinin bedelini hesapla ve kayda yaz")} CIKTI = {"sayac_oku": ("onceki", "simdiki", "tip", "bolge"), "tuketim": ("m3",), "tarife": ("tutar",), "belge_ara": ("kod",)} SONUC = {"tuketim": "m3", "tarife": "tutar", "belge_ara": "kod"} BASLANGIC = {k: dict(v) for k, v in ABONE.items()} def akis(n=72): """Ilk kumenin abonelerine sorulan n soruluk gorev akisi.""" k = [] for i in range(n): r = uretec(TOHUM + 7919 * (i + 101)) a = GOREV[int(r() * 24)]["abone"] t = list(PLAN)[ayrik(r(), [0.30, 0.22, 0.20, 0.28])] k.append({"ad": f"H{i + 1:02d}", "tur": t, "abone": a, "dizi": PLAN[t][0], "istek": PLAN[t][1].format(a=a)}) return k def yeni_donem(i): """Her alti gorevde bir, on iki abone yeni bir donem okumasi alir.""" r = uretec(TOHUM + 61 * i) for _ in range(12): a = ABONE[f"A{1 + int(r() * 60):03d}"] a["onceki"] = a["simdiki"] a["simdiki"] = a["onceki"] + int(r() * 70) def gecerli(kyt): """Kaydin alanlari ortamin o andaki degerleriyle hala ortusuyor mu.""" if kyt["abone"] is None: return True a = ABONE[kyt["abone"]] f = a["simdiki"] - a["onceki"] m3 = f + 100000 if f < 0 else f su = dict(a, m3=m3, tutar=_bedel(m3, a["tip"])) return all(su.get(x) == v for x, v in kyt["alan"].items()) def ajan_e(g, kyt, tohum=TOHUM, en_cok_adim=8): """Ortak dongu; baslangic durumu bellekteki kayittan gelir.""" r = uretec(tohum ^ izno(g["ad"])) alan = {"abone": g["abone"], "anahtar": g["istek"], "sutun": "bedel"} alan.update(kyt["alan"] if kyt else {}) adim, k, dizi, yolda = 0, 0, g["dizi"], {} while k < len(dizi) and dizi[k] in CIKTI and all(x in alan for x in CIKTI[dizi[k]]): alan["sonuc"] = alan.get(SONUC.get(dizi[k]), alan.get("sonuc")) k += 1 if k == len(dizi): return {"adim": 0, "yanit": alan.get("sonuc"), "yolda": {}} while adim < en_cok_adim: adim += 1 hedef = dizi[k] if k < len(dizi) else None if hedef is None: if r() < 0.88: break sec = ARAC_ADI[int(r() * len(ARAC_ADI))] else: sec = hedef if r() < gorme(k + 1) else ARAC_ADI[int(r() * len(ARAC_ADI))] if sec == "kayit_yaz": alan["deger"] = alan.get("sonuc") s = cagir_arac(sec, alan) if "hata" in s: continue alan.update({x: v for x, v in s.items() if x != "hata"}) if sec in SONUC: alan["sonuc"] = s[SONUC[sec]] if sec == hedef: yolda.update({x: s[x] for x in CIKTI.get(sec, ()) if x in s}) k += 1 return {"adim": adim, "yanit": alan.get("sonuc"), "yolda": yolda} def kosum(esik, tohum=TOHUM, n=72): """Eskitme esigi: yasi esikten buyuk kayit dusurulur.""" for x, v in BASLANGIC.items(): ABONE[x].update(v) CAGRI[0] = 0 bellek = {} s = dict.fromkeys(("okuma", "bayat", "atilan", "kayip", "adim", "dogru"), 0) for i, g in enumerate(akis(n)): if i and i % 6 == 0: yeni_donem(i) for a in [x for x, k in bellek.items() if i - k["zaman"] > esik]: s["atilan"] += 1 s["kayip"] += gecerli(bellek.pop(a)) ah = g["istek"] if g["tur"] == "belge" else g["abone"] kyt = bellek.get(ah) if kyt: s["okuma"] += 1 s["bayat"] += not gecerli(kyt) c = ajan_e(g, kyt, tohum) s["adim"] += c["adim"] s["dogru"] += c["yanit"] == dogru_yanit(g) if c["yolda"]: bellek[ah] = {"alan": c["yolda"], "zaman": i, "abone": None if g["tur"] == "belge" else g["abone"]} return (s["okuma"], s["bayat"] / max(s["okuma"], 1), s["atilan"], s["kayip"] / max(s["atilan"], 1), s["adim"], CAGRI[0], s["dogru"] / n) print("esik okuma bayat atilan kayip adim cagri basarim | 2. kosum") for e in (10 ** 6, 32, 24, 16, 8, 4, 1): a, b = kosum(e), kosum(e, TOHUM + 1) print(f"{e if e < 100 else '--':>4} {a[0]:>6} {a[1]:>7.4f} {a[2]:>7} {a[3]:>7.4f}" f" {a[4]:>5} {a[5]:>5} {a[6]:>7.4f} | {b[6]:.4f}")
esik okuma bayat atilan kayip adim cagri basarim | 2. kosum -- 53 0.4528 0 0.0000 138 108 0.6389 | 0.5972 32 42 0.3333 18 0.3333 176 139 0.7778 | 0.7361 24 36 0.2222 23 0.4783 201 158 0.8194 | 0.7778 16 31 0.0968 32 0.6250 220 171 0.8750 | 0.8611 8 23 0.0870 41 0.7805 246 193 0.8889 | 0.8611 4 13 0.0000 55 0.8909 283 221 0.9028 | 0.8750 1 3 0.0000 67 0.9701 315 246 0.9306 | 0.8889
Eşiksiz satır belleğin en verimli ve en yanlış hâlidir: 53 okuma, 138 adım, ama okumaların 0,4528’i bayat ve başarım 0,6389 — görevlerin üçte birinden fazlasında kullanıcıya geçen dönemin sayısı söyleniyor.
Eşik sıkıldıkça iki sütun zıt yönlere gidiyor. Bayat pay 0,4528’den 0,3333’e, 0,2222’ye, 0,0968’e ve 0,0000’a iniyor, başarım 0,6389’dan 0,9306’ya çıkıyor. Aynı satırlarda kayıp pay 0,0000’dan 0,6250’ye ve 0,9701’e tırmanıyor: eşik bire indiğinde düşürülen 67 kaydın 65’i düşürüldüğü anda hâlâ geçerliydi. Bedel adım olarak da yazılıyor — 138 adım 315’e, araç çağrısı 108’den 246’ya çıkıyor.
Yaş, Geçerliliğin Vekilidir
Kayıp pay sütunu eskitmenin ne olduğunu tek başına anlatıyor. Eşik, bir kaydın geçerli olup olmadığını sormaz; kaç görev önce yazıldığını sorar. Yaş, geçerliliğin bir vekilidir ve bu akışta zayıf bir vekildir: her altı görevde yalnız on iki abone yenileniyor, yani bayatlama bir olasılıktır, yaşın belirlediği bir kesinlik değil.
Nerede durulacağını iki koşum farkı söylüyor. Eşiksiz satır iki koşumda 0,6389 ve 0,5972 veriyor; bant 0,0417. Eşiği sekize sıkmanın kazancı 0,2500, bandın altı katı — ölçülmüştür. Sekizden bire sıkmanın kazancı ise 0,8889 ile 0,9306 arasında, tam bandın kendisi kadar; ikinci koşumda aynı kazanç 0,0278’e iniyor. Bu fark bulgu olarak ilan edilemez: eşiği sekizin altına indirmek 69 adım ve 53 araç çağrısı daha ödetiyor, karşılığında ölçülmemiş bir kazanç veriyor. Ölçmek isteyen görev sayısını büyütmeli ya da yenileme sıklığını bir ayar olarak süpürmelidir.
Bayat ve kayıp payları iki koşumda birebir aynı çıkıyor: bu iki sayı araç seçimi çekilişine değil, yenileme takvimi ile eşiğin ilişkisine bağlıdır. Eskitme eşiği verinin değişme sıklığından bağımsız seçilemez.
Özet
- Bellekteki kayıt hata vermeden yanlışa döner ve doğru kayıttan ayırt edilemez.
- Eşiksiz bellekte okumaların 0,4528’i bayat ve başarım 0,6389; eşik bire indiğinde bayat pay 0,0000, başarım 0,9306.
- Aynı süpürmede düşürülen kayıtların hâlâ geçerli olan payı 0,0000’dan 0,9701’e çıkıyor ve adım 138’den 315’e tırmanıyor.
- Eşik, kaydın geçerliliğini değil yaşını sorar; yaş bir vekildir ve bu yenileme takviminde bayat payı sıfırlamanın bedeli geçerli kayıtların neredeyse tamamını atmaktır.
- Eşiği sekizin altına sıkmanın kazandırdığı başarım iki koşum farkının kendisi kadardır ve ölçülmemiş sayılır; sekizden bire inmek 69 adım daha ödetiyor.
Sonraki Adım
Bu konu ajanı donattı: araç tanımı, yürütme, kod çalıştırma, dosya ve terminal yüzeyi, dış bilgi, kısa ve uzun süreli bellek, sıkıştırma ve eskitme. Bir önceki konuyla birlikte on altı derste bir ajan kuruldu, nerede duracağı yazıldı, denetim noktaları kondu ve eline araçlar verildi. Her derste bir düzeneğin sayısı ve bedeli basıldı — ama her biri yalnız o dersin düzeneğine bakan bir ölçüyle okundu. Bütününe bakan soru hiç sorulmadı: bu ajanın çalıştığını nereden biliyoruz. Doğru yanıt veren bir koşumun doğru yolu izleyip izlemediği, bir aracın tek başına sınandığında görünmeyen kusurunun akış içinde çıkıp çıkmadığı ve üretimde koşan bir döngü hakkında hangi kaydın konuşabildiği ele alınmadı. Sonraki konu bu soruyla açılır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.