Ders 06 / 20
Paylaşılan Katmanlar ve Bağımlılıklar
Paket boyutu ile soğuk başlangıç arasındaki ilişki taranır: bağımlılıklar paylaşılan bir katmana taşındığında paket küçülür ama çekilen bayt değişmez. Sürüm sabitlemenin depolama bedeli, katman güncellemesinin yarıçapı ve kullanılmayan bağımlılığın taşınan bayt karşılığı sayılır.
İçindekiler
Sürüm kaydırma ölçümünde soğuk başlangıç bin sekiz yüz milisaniyelik bir sabit gibi davranıyordu. Değildir. O sayı işlevin paketinden gelir: paket ne kadar büyükse çekilecek, açılacak ve yüklenecek o kadar çok bayt vardır. Buranın sorusu şudur — paketi küçültmenin yolları nelerdir ve her yolun faturası nedir?
Buradaki katman, bir konteyner imajının katmanıyla aynı sözcüğü paylaşır ama farklı bir nesnedir: orada katman bir dosya sistemi anlık görüntüsüydü, burada işlevin paketine yayım sırasında eklenen ortak bir bağımlılık kümesidir.
- IH31. Kurgusal bölgesel ölçüm ağının dokuz işlevi ve yedi kalemlik bir bağımlılık kataloğu vardır. Boyutlar, modül sayıları ve kullanım ilişkileri kurgudur.
- IH32. Soğuk başlangıç dört kalemin toplamıdır: boyuttan bağımsız yüz seksen milisaniyelik taban, saniyede yirmi megabayt çekme, megabayt başına on iki milisaniye açma ve modül başına sıfır virgül otuz beş milisaniye yükleme. Ağ değişkenliği ve sıkıştırma modellenmiyor.
- IH33. Bir bağımlılık en az dört işlevde geçiyorsa paylaşılan katmana alınır. Eşiğin kendisi bir tasarım kararıdır ve taranmıyor.
- IH34. Katman soğuk başlangıçta paketle birlikte çekilir. Ana makine önbelleği tek bir isabet oranıyla modellenir; isabet hâlinde katmanın bedeli sıfırdır.
- IH35. Her işlev günde kırk soğuk başlangıç yaşar. Trafiğin gün içine dağılımı modellenmiyor.
- IH36. Canlı katman sürümlerinin dağılımı kurgudur: dört sürüm, sırasıyla üç, iki, üç ve bir işleve sabitlenmiş.
Bir Soğuk Başlangıç Neyin Toplamı
Ölçülen şey gerçek bir yayım değil, node ile kurulan bir modeldir. Katalog, her bağımlılığın
boyutunu ve modül sayısını tutar; dokuz işlevin her biri gerçekten çağırdığı bağımlılıkları
listeler. Bir kalem hiçbir listede geçmez.
// paket.mjs — paket boyutu, soguk baslangic ve paylasilan katman modeli; olcum degil, modeldir export const BANT_MB_SN = 20; // kurgu: paketi cekme bant genisligi export const ACMA_MS_MB = 12; // bir MB'i acmanin suresi export const MODUL_MS = 0.35; // modul basina yukleme suresi export const TABAN_MS = 180; // calisma zamani baslatma tabani, boyuttan bagimsiz export const SOGUK_GUN = 40; // kurgu: islev basina gunluk soguk baslangic sayisi export const KATMAN_ESIK = 4; // bu kadar islevde gecen bagimlilik paylasilan katmana alinir // Kurgusal olcum aginin bagimlilik katalogu: boyut (MB) ve modul sayisi. export const KATALOG = { oc: { ad: 'olcum cozumleyici', mb: 9.4, modul: 320 }, sd: { ad: 'sema dogrulayici', mb: 4.8, modul: 210 }, ve: { ad: 'veri erisim katmani', mb: 6.3, modul: 240 }, ts: { ad: 'tarih-saat kitapligi', mb: 2.1, modul: 90 }, sf: { ad: 'sifreleme yardimcilari', mb: 1.6, modul: 60 }, rb: { ad: 'rapor bicimlendirici', mb: 14.2, modul: 540 }, gu: { ad: 'gorsel uretici', mb: 21.5, modul: 760 }, }; export const KENDI = { mb: 1.2, modul: 45 }; // her islevin kendi kodu // Dokuz islev ve gercekten cagirdigi bagimliliklar. 'gu' hicbir islevde gecmiyor. export const ISLEVLER = { 'okuma-dogrulama': ['oc', 'sd', 've', 'ts', 'sf'], 'okuma-yazma': ['oc', 've', 'ts', 'sf'], 'fatura-uretimi': ['oc', 'sd', 've', 'ts', 'sf', 'rb'], 'fatura-gonderimi': ['ve', 'ts', 'sf', 'rb'], 'saha-bildirimi': ['ve', 'ts', 'sf'], 'gece-toplu-is': ['oc', 'sd', 've', 'ts', 'sf'], 'sayac-kayit': ['sd', 've', 'ts', 'sf'], 'tarife-guncelleme': ['sd', 've', 'sf'], 'saglik-ucu': ['ve'], }; export const kullanan = (k) => Object.values(ISLEVLER).filter((d) => d.includes(k)).length; export const boyut = (ks) => ks.reduce((a, k) => ({ mb: a.mb + KATALOG[k].mb, modul: a.modul + KATALOG[k].modul }), { ...KENDI }); // Soguk baslangic: sabit taban + cekme + acma + modul yukleme. Bayt hem cekilir hem acilir. export const soguk = (b) => TABAN_MS + (1000 * b.mb) / BANT_MB_SN + ACMA_MS_MB * b.mb + MODUL_MS * b.modul; export const satir = (g, ...x) => x.map((v, i) => String(v).padEnd(g[i])).join(''); export const mb = (x) => `${x.toFixed(1)} MB`; export const ek = (b) => soguk(b) - TABAN_MS; // tabani cikarilmis cekme + acma + yukleme suresi
// kosum1.mjs — paket boyutu ile soguk baslangic arasindaki iliski ve dort paketleme duzeni import { KATALOG, ISLEVLER, KENDI, KATMAN_ESIK, SOGUK_GUN, BANT_MB_SN, ACMA_MS_MB, MODUL_MS, kullanan, boyut, soguk, satir, mb } from './paket.mjs'; const hepsi = Object.keys(KATALOG), n = Object.keys(ISLEVLER).length; console.log(`${n} islev | cekme ${BANT_MB_SN} MB/sn | acma ${ACMA_MS_MB} ms/MB | modul ${MODUL_MS} ms`); console.log(`kullanim sayisi: ${hepsi.map((k) => `${k} ${kullanan(k)}`).join(', ')} | katman esigi ${KATMAN_ESIK}`); console.log('\npaket boyutu -> soguk baslangic (modul sayisi boyutla orantili varsayilir, 36 modul/MB)'); console.log(satir([10, 9, 12, 11, 11], 'boyut', 'modul', 'cekme ms', 'acma ms', 'yukleme ms') + 'soguk baslangic'); for (const x of [2, 8, 16, 26, 40, 61]) { const b = { mb: x, modul: Math.round(36 * x) }; console.log(satir([10, 9, 12, 11, 11], mb(x), b.modul, Math.round(1000 * x / BANT_MB_SN), Math.round(ACMA_MS_MB * x), Math.round(MODUL_MS * b.modul)) + `${Math.round(soguk(b))} ms`); } // Dort paketleme duzeni. C ve D ayni icerigi tasir: fark yalnizca baytin nerede durdugudur. const katmanKod = hepsi.filter((k) => kullanan(k) >= KATMAN_ESIK), katman = boyut(katmanKod); katman.mb -= KENDI.mb; katman.modul -= KENDI.modul; // katmanda kendi kod bulunmaz const duzen = (ad, paketi, katmanli = false) => { const p = Object.values(ISLEVLER).map((d) => boyut(paketi(d))); const cekilen = p.map((x) => (katmanli ? { mb: x.mb + katman.mb, modul: x.modul + katman.modul } : x)); const c = cekilen.map(soguk), boy = p.map((x) => x.mb); return { ad, enKucuk: Math.min(...boy), enBuyuk: Math.max(...boy), depo: boy.reduce((a, b) => a + b, 0) + (katmanli ? katman.mb : 0), sogukEnAz: Math.min(...c), sogukEnCok: Math.max(...c) }; }; const D = [46, 16, 16, 12]; console.log('\npaketleme duzenleri — dokuz islev'); console.log(satir(D, 'duzen', 'paket en kucuk', 'paket en buyuk', 'depolanan') + 'soguk baslangic araligi'); for (const r of [ duzen('A. her islev katalogun tamamini paketler', () => hepsi), duzen('B. hic kullanilmayan ayiklanir', () => hepsi.filter((k) => kullanan(k) > 0)), duzen('C. her islev yalniz kullandigini paketler', (d) => d), duzen('D. esigi gecen bagimliliklar katmana tasinir', (d) => d.filter((k) => kullanan(k) < KATMAN_ESIK), true)]) { console.log(satir(D, r.ad, mb(r.enKucuk), mb(r.enBuyuk), mb(r.depo)) + `${Math.round(r.sogukEnAz)}-${Math.round(r.sogukEnCok)} ms`); } const gu = KATALOG.gu, tekSoguk = 1000 * gu.mb / BANT_MB_SN + ACMA_MS_MB * gu.mb + MODUL_MS * gu.modul; console.log(`\nhic kullanilmayan "${gu.ad}" (${mb(gu.mb)}, ${gu.modul} modul) A duzeninde kalirsa:`); console.log(` her soguk baslangica ${Math.round(tekSoguk)} ms, gunde ${n * SOGUK_GUN} soguk baslangicta ` + `${(n * SOGUK_GUN * tekSoguk / 1000 / 60).toFixed(1)} dk ve ${(n * SOGUK_GUN * gu.mb / 1024).toFixed(1)} GB tasinan bayt`); console.log(` depolamada ${mb(n * gu.mb)}; ayiklanmasi paketi ${mb(gu.mb)} kucultur, kod degisikligi gerektirmez`);
9 islev | cekme 20 MB/sn | acma 12 ms/MB | modul 0.35 ms kullanim sayisi: oc 4, sd 5, ve 9, ts 7, sf 8, rb 2, gu 0 | katman esigi 4 paket boyutu -> soguk baslangic (modul sayisi boyutla orantili varsayilir, 36 modul/MB) boyut modul cekme ms acma ms yukleme ms soguk baslangic 2.0 MB 72 100 24 25 329 ms 8.0 MB 288 400 96 101 777 ms 16.0 MB 576 800 192 202 1374 ms 26.0 MB 936 1300 312 328 2120 ms 40.0 MB 1440 2000 480 504 3164 ms 61.0 MB 2196 3050 732 769 4731 ms paketleme duzenleri — dokuz islev duzen paket en kucuk paket en buyuk depolanan soguk baslangic araligi A. her islev katalogun tamamini paketler 61.1 MB 61.1 MB 549.9 MB 4761-4761 ms B. hic kullanilmayan ayiklanir 39.6 MB 39.6 MB 356.4 MB 3162-3162 ms C. her islev yalniz kullandigini paketler 7.5 MB 39.6 MB 185.0 MB 745-3162 ms D. esigi gecen bagimliliklar katmana tasinir 1.2 MB 15.4 MB 63.4 MB 2093-3162 ms hic kullanilmayan "gorsel uretici" (21.5 MB, 760 modul) A duzeninde kalirsa: her soguk baslangica 1599 ms, gunde 360 soguk baslangicta 9.6 dk ve 7.6 GB tasinan bayt depolamada 193.5 MB; ayiklanmasi paketi 21.5 MB kucultur, kod degisikligi gerektirmez
İlk tarama soğuk başlangıcın nereden geldiğini ayırıyor. İki megabayttan altmış bire çıkıldığında süre üç yüz yirmi dokuz milisaniyeden dört bin yedi yüz otuz bire gidiyor; aradaki farkın tamamı boyuta bağlıdır. Megabayt başına düşen yük yetmiş dört virgül altı milisaniyedir: elli çekme, on iki açma, on iki virgül altı modül yükleme. Sabit taban yüz seksende kalır — otuz megabaytlık bir pakette soğuk başlangıcın yüzde doksanından fazlası baytın kendisidir.
Dört Paketleme Düzeni
İkinci tablo aynı dokuz işlevi dört farklı paketleme düzeniyle kuruyor. A düzeninde her işlev kataloğun tamamını taşır; B’de hiç kullanılmayan kalem ayıklanır; C’de her işlev yalnız çağırdığını paketler; D’de eşiği geçen bağımlılıklar paylaşılan katmana taşınır.
A’dan B’ye geçiş bedava bir kazançtır: kod değişmez, paket altmış bir virgül birden otuz dokuz virgül altıya, soğuk başlangıç dört bin yedi yüz altmış birden üç bin yüz altmış ikiye iner. C, her işleve kendi listesini vererek en küçük paketi yedi virgül beşe indirir ve soğuk başlangıç aralığını yedi yüz kırk beş ile üç bin yüz altmış iki arasına açar.
D satırı ise dersin asıl sayısını yazıyor. Paket boyutu bir virgül iki megabayta kadar iner — C’nin altıda biri — ama soğuk başlangıcın alt ucu yedi yüz kırk beşten iki bin doksan üçe çıkar. Sebebi basittir: katmandaki yirmi dört virgül iki megabayt yok olmadı, yalnız paketin dışına alındı; soğuk başlangıçta yine çekilir. Dahası, katmandaki her şeyi kullanmayan işlevler artık kullanmadıkları baytı da çekmektedir. Paket boyutunu ölçüt almak burada yanıltır; ölçülecek olan çekilen bayttır.
Son satırlar hiç kullanılmayan kalemin faturasını yazıyor. Yirmi bir virgül beş megabaytlık görsel üretici her soğuk başlangıca bin beş yüz doksan dokuz milisaniye ekler; günde üç yüz altmış soğuk başlangıçta dokuz virgül altı dakika ve yedi virgül altı gigabayt taşınan bayt eder.
Katman Baytı Yok Etmez, Yerini Değiştirir
// kosum2.mjs — katman onbellegi, surum sabitleme ve bir katman guncellemesinin yaricapi import { KATALOG, ISLEVLER, KENDI, KATMAN_ESIK, TABAN_MS, kullanan, boyut, soguk, ek, satir, mb } from './paket.mjs'; const hepsi = Object.keys(KATALOG), n = Object.keys(ISLEVLER).length; const katmanKod = hepsi.filter((k) => kullanan(k) >= KATMAN_ESIK), katman = boyut(katmanKod); katman.mb -= KENDI.mb; katman.modul -= KENDI.modul; const paketC = Object.values(ISLEVLER).map((d) => boyut(d)); const paketD = Object.values(ISLEVLER).map((d) => boyut(d.filter((k) => kullanan(k) < KATMAN_ESIK))); console.log(`paylasilan katman: ${katmanKod.join(', ')} = ${mb(katman.mb)}, ${katman.modul} modul`); // Katman ana makinede onbelleklenirse soguk baslangicta yeniden cekilmez. Isabet orani taranir. const O = [10, 20, 20, 18]; console.log(satir(O, 'isabet', 'D en kucuk islev', 'D en buyuk islev', 'D ortalama') + 'C ortalama'); const ortC = paketC.map(soguk).reduce((a, b) => a + b, 0) / n; for (const h of [0, 0.25, 0.5, 0.75, 1]) { const d = paketD.map((p) => TABAN_MS + ek(p) + (1 - h) * ek(katman)); console.log(satir(O, `%${h * 100}`, `${Math.round(Math.min(...d))} ms`, `${Math.round(Math.max(...d))} ms`, `${Math.round(d.reduce((a, b) => a + b, 0) / n)} ms`) + `${Math.round(ortC)} ms`); } // Katman surumlenir ve her islev bir surume sabitlenir. Kurgu dagilim: kac islev hangi surumde. const SABITLEME = { v4: 3, v3: 2, v2: 3, v1: 1 }; const canli = Object.keys(SABITLEME).length; console.log(`\nsurum sabitleme — ${canli} katman surumu canli tutuluyor`); console.log(` ${Object.entries(SABITLEME).map(([s, k]) => `${s}: ${k} islev`).join(' | ')}`); console.log(` toplam katman depolamasi ${mb(canli * katman.mb)} (tek surum varsayimi ${mb(katman.mb)}); ` + `tek surume inmek ${n - Math.max(...Object.values(SABITLEME))} islevin yeniden yayimini gerektirir`); // Bir bagimlilik guncellemesinin iki maliyeti: kac yayim gerekir ve kac islevi ayni anda etkiler. const Y = [40, 10, 22]; console.log('\nbir bagimlilik guncellemesi'); console.log(satir(Y, 'bagimlilik nerede duruyor', 'yayim', 'ayni anda etkilenen') + 'depolanan'); for (const [ad, yayim, yaricap, depo] of [ ['C — her paketin icinde ayri ayri', n, 1, paketC.reduce((a, b) => a + b.mb, 0)], ['D — katmanda, surum sabitlenmis', n, 1, paketD.reduce((a, b) => a + b.mb, 0) + canli * katman.mb], ['D — katmanda, takma adi izliyor', 1, n, paketD.reduce((a, b) => a + b.mb, 0) + katman.mb]]) { console.log(satir(Y, ad, yayim, `${yaricap} islev`) + mb(depo)); }
paylasilan katman: oc, sd, ve, ts, sf = 24.2 MB, 920 modul isabet D en kucuk islev D en buyuk islev D ortalama C ortalama %0 2093 ms 3162 ms 2330 ms 1730 ms %25 1637 ms 2706 ms 1875 ms 1730 ms %50 1181 ms 2251 ms 1419 ms 1730 ms %75 726 ms 1795 ms 963 ms 1730 ms %100 270 ms 1340 ms 508 ms 1730 ms surum sabitleme — 4 katman surumu canli tutuluyor v4: 3 islev | v3: 2 islev | v2: 3 islev | v1: 1 islev toplam katman depolamasi 96.8 MB (tek surum varsayimi 24.2 MB); tek surume inmek 6 islevin yeniden yayimini gerektirir bir bagimlilik guncellemesi bagimlilik nerede duruyor yayim ayni anda etkilenen depolanan C — her paketin icinde ayri ayri 9 1 islev 185.0 MB D — katmanda, surum sabitlenmis 9 1 islev 136.0 MB D — katmanda, takma adi izliyor 1 9 islev 63.4 MB
İlk tablo katmanın ne zaman kazandırdığını gösteriyor. Önbellek isabeti sıfırken D düzeninin ortalaması iki bin üç yüz otuz, C’nin ortalaması bin yedi yüz otuz milisaniyedir — katman ortalamayı altı yüz milisaniye kötüleştirir. Yüzde elli isabette D bin dört yüz on dokuza iner ve C’yi geçer; başabaş nokta yüzde otuz üç civarındadır, tam isabette D beş yüz sekize düşer. Katmanın değeri katmanın kendisinde değil, ana makinenin onu ne sıklıkla elinde tuttuğundadır — ve bu, işlevi yazanın kararı değildir.
Sürüm Sabitleme ve Güncellemenin Yarıçapı
Sürüm sabitleme tablosu ikinci bedeli yazıyor. Dokuz işlev dört ayrı katman sürümüne sabitlenmiştir ve hiçbiri düşürülemez, çünkü her birinin kullanıcısı vardır. Depolanan katman baytı yirmi dört virgül ikiden doksan altı virgül sekize çıkar; hepsini tek sürüme çekmek altı işlevin yeniden yayımını gerektirir.
Son tablo devredilen kararın faturasını kesiyor. Bağımlılık her paketin içinde ayrı ayrı dururken bir güncelleme dokuz yayım ister, ama her yayım tek bir işlevi etkiler: yarıçap birdir, aşamalı yayılabilir. Katmana taşındığında ve sürüm sabitlendiğinde yayım sayısı yine dokuzdur — sabitleme, katmanın “tek yerden güncelle” vaadini geri alır — kazanç yalnız depolamadadır, yüz seksen beşten yüz otuz altı megabayta. Sabitleme bırakılıp katman bir takma adı izlediğinde yayım bire iner; karşılığında yarıçap dokuza çıkar. Tek yazma dokuz işlevi aynı anda değiştirir ve kusurlu bir katman sürümü dokuzunu birden bozar.
Özet
- Soğuk başlangıcın megabayt başına yükü yetmiş dört virgül altı milisaniyedir: elli çekme, on iki açma, on iki virgül altı modül yükleme.
- Hiç kullanılmayan kalemi ayıklamak paketi otuz dokuz virgül altı megabayta, soğuk başlangıcı üç bin yüz altmış iki milisaniyeye indirir ve kod değişikliği gerektirmez; taşınan bayt günde yedi virgül altı gigabayt azalır.
- Bağımlılıkları katmana taşımak paketi bir virgül iki megabayta düşürür ama soğuk başlangıcın alt ucunu yedi yüz kırk beşten iki bin doksan üç milisaniyeye çıkarır: bayt yok olmadı, yer değiştirdi.
- Katman ancak ana makine önbelleği yüzde otuz üçün üstünde isabet ettiğinde kazandırır; sıfır isabette ortalamayı altı yüz milisaniye kötüleştirir.
- Dört katman sürümü canlı tutulduğunda depolanan katman baytı dört katına çıkar; tek sürüme inmek altı işlevin yeniden yayımını ister.
- Bir güncelleme paket içinde dokuz yayım ve bir işlevlik yarıçap, sabitlenmiş katmanda yine dokuz yayım, takma adı izleyen katmanda tek yayım ve dokuz işlevlik yarıçap demektir.
Sonraki Adım
Paket ölçüldü, katman ölçüldü, soğuk başlangıcın hangi kaleminin nereden geldiği yazıldı. Bunların hepsi bir varsayımı paylaşıyordu: iş, işleve uyuyor. Süre sınırına sığıyor, durumu dışarıda tutulabiliyor, bir istek gelince başlayıp bir yanıtla bitiyor. Her iş böyle değildir. Sonraki ders beş iş türünü süre, durum ve maliyet ekseninde yan yana koyar; her tür için eşiği aşan kalemi adıyla yazar ve sığmayan işi parçalayarak sığdırmanın bedelini — adım sayısı, ara durum saklama, hata yüzeyi — sayar. Sonunda tek bir tablo kalır: hangi iş sunucusuza uyar, hangisi uymaz ve neden.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.