İçeriğe geç
academia.sh

Ders 03 / 20

Soğuk Başlangıç

Bir sıcak havuz modeli koşturularak isteğin örnek bulup bulamadığı sayılır: üç kurgu trafik profilinde soğuk çağrı oranı, gecikmeye eklenen süre ve kuyruğa giren istek ölçülür; havuz ömrü sıfırdan bin sekiz yüz saniyeye taranarak soğuk oranın düştüğü eşik ile karşılığında boşta duran örnek-saniye çıkarılır ve üç azaltma yolu ayrı ayrı fiyatlandırılır.

İçindekiler

Önceki iki dersin gecikme sayıları tek bir varsayıma yaslandı: çağrı geldiğinde işlevi çalıştıracak bir örnek hazır bekliyordu. Kapasite kararı devredildiği için bu her zaman doğru değildir. Örnekler istek geldikçe yaratılır, boşta kalınca geri alınır; hazır örnek bulamayan istek soğuk başlangıç yaşar — çalışma zamanının kurulması, paketin açılması ve başlatma kodu istek yolunun içine girer.

M23/K02 aynı dengeyi — imaja gömülen kalemle açılışta kalan iş — saniye ölçeğinde ölçtü; o ölçüm tekrarlanmaz. Burada ölçek milisaniye, nesne imaj değil pakettir. Sorulan tek bir orandır: kaç çağrı soğuk başlıyor, bu neye bağlı ve azaltmanın bedeli ne.

IH13. Ölçüm penceresi 1800 saniyedir; bölgesel ölçüm ağının üç kurgu trafik profili kendi yazılan bir üreteçle kurulur, tohum 20260804’tür. IH14. Sıcak çağrı 400 ms tutar, soğuk çağrıya 900 ms eklenir; bu ek gecikmeye girer, faturaya girmez. IH15. Profiller: saha bildirimi seyrek (ortalama 90 sn ara), okuma doğrulaması düzenli (ortalama 250 ms ara), gece toplu işlemesi ani (600 saniyede bir, 60 saniyelik patlama, 25 ms ara). IH16. Havuz ömrü, bir örneğin boşta kalıp geri alınmadan önce beklediği süredir; taban değer 300 saniyedir. IH17. İşlevin eşzamanlılık payı 40’tır; havuz dolduğunda gelen istek kuyruğa girer, düşmez. IH18. Fiyatlar kurgu birimle yazılır: çağrı 0,0005, işlem milisaniyesi 0,0000025, önceden ısıtılan örnek-saniye 0,0002 birim.

Havuzda Örnek Var mı

Model tek kural üzerinedir: havuzda boşta örnek varsa çağrı sıcaktır; yoksa ve pay dolmamışsa yeni örnek yaratılır; pay da dolmuşsa istek kuyruğa girer.

// olcum-agi/sicak-havuz.mjs — istek geldiginde havuzda ornek varsa sicak, yoksa soguk cagri (model)

export const PENCERE = 1800000, ISLEM = 400, SOGUK = 900;   // ms: olcum penceresi, isleme, soguk ek
export const OMUR = 300000, SINIR = 40;                     // ms bosta tutma, islevin eszamanlilik payi
export const CAGRI_B = 0.0005, MS_B = 0.0000025, ISIT_B = 0.0002;   // kurgu birim

export const uretec = (t) => { let s = t >>> 0; return () => {
  s ^= s << 13; s >>>= 0; s ^= s >>> 17; s ^= s << 5; s >>>= 0; return s / 4294967296; }; };

// Uc kurgu trafik profili: saha bildirimi seyrek, dogrulama duzenli, gece toplu islemesi ani.
export const PROFIL = {
  seyrek: { ara: 90000, pencereler: [[0, PENCERE]] },
  duzenli: { ara: 250, pencereler: [[0, PENCERE]] },
  ani: { ara: 25, pencereler: [[0, 60000], [600000, 660000], [1200000, 1260000]] },
};

export const varislar = (ad, tohum = 20260804) => {
  const r = uretec(tohum), p = PROFIL[ad], v = [];
  for (const [bas, son] of p.pencereler) {
    let t = bas;
    while (t < son) { t += -Math.log(1 - r()) * p.ara; if (t < son) v.push(t); }
  }
  return v;
};

const yuzde = (a, p) => [...a].sort((x, y) => x - y)[Math.floor(a.length * p)];
const bosta = (o, son) => Math.max(0, son - o.dogum - o.mesgul) / 1000;

// Havuz: her ornek bosaldigi anda "bos" damgasi alir; damga uzerinden omur dolarsa geri alinir.
export const kos = (varis, { omur = OMUR, sinir = SINIR, soguk = SOGUK, islem = ISLEM,
  isit = 0, ekCagri = 0 } = {}) => {
  const havuz = [];
  for (let i = 0; i < isit; i++) havuz.push({ bos: 0, dogum: 0, mesgul: 0, sabit: true });
  let sogukSayi = 0, kuyrukta = 0, enUzunBekleme = 0, bostaSn = 0, enCok = havuz.length, isSuresi = 0;
  const gecikme = [];
  for (const t of varis) {
    for (let i = havuz.length - 1; i >= 0; i--) {
      const o = havuz[i];
      if (!o.sabit && o.bos + omur < t) { bostaSn += bosta(o, o.bos + omur); havuz.splice(i, 1); }
    }
    let ornek = havuz.find((o) => o.bos <= t), bas = t, ek = 0, bekleme = 0;
    if (!ornek && havuz.length < sinir) {
      ornek = { bos: 0, dogum: t, mesgul: 0, sabit: false };
      havuz.push(ornek); ek = soguk; sogukSayi++;
    } else if (!ornek) {
      ornek = havuz.reduce((a, b) => (b.bos < a.bos ? b : a));
      bekleme = ornek.bos - t; bas = ornek.bos; kuyrukta++;
      if (bekleme > enUzunBekleme) enUzunBekleme = bekleme;
    }
    const sure = ek + islem + ekCagri;
    ornek.bos = bas + sure; ornek.mesgul += sure; isSuresi += sure;
    gecikme.push(bekleme + sure);
    if (havuz.length > enCok) enCok = havuz.length;
  }
  for (const o of havuz) bostaSn += bosta(o, o.sabit ? PENCERE : Math.min(PENCERE, o.bos + omur));
  return { cagri: varis.length, soguk: sogukSayi, oran: sogukSayi / varis.length,
    ortGecikme: gecikme.reduce((a, b) => a + b, 0) / gecikme.length, g99: yuzde(gecikme, 0.99),
    kuyrukta, enUzunBekleme, enCok, bostaSn,
    maliyet: varis.length * CAGRI_B + isSuresi * MS_B + isit * (PENCERE / 1000) * ISIT_B };
};

if (import.meta.url === `file://${process.argv[1]}`) {
  console.log(`pencere ${PENCERE / 1000} sn, isleme ${ISLEM} ms, soguk ek ${SOGUK} ms, ` +
    `omur ${OMUR / 1000} sn, pay ${SINIR}`);
  console.log("\n" + "profil".padEnd(10) + "cagri".padEnd(9) + "soguk".padEnd(8) + "soguk oran".padEnd(12) +
    "ort gecikme".padEnd(14) + "99. dilim".padEnd(12) + "kuyruga giren".padEnd(15) +
    "en uzun bekleme".padEnd(17) + "en cok ornek".padEnd(14) + "bosta ornek-sn");
  for (const ad of Object.keys(PROFIL)) {
    const s = kos(varislar(ad));
    console.log(ad.padEnd(10) + String(s.cagri).padEnd(9) + String(s.soguk).padEnd(8) +
      `%${(s.oran * 100).toFixed(2)}`.padEnd(12) + `${s.ortGecikme.toFixed(0)} ms`.padEnd(14) +
      `${s.g99.toFixed(0)} ms`.padEnd(12) + String(s.kuyrukta).padEnd(15) +
      `${s.enUzunBekleme.toFixed(0)} ms`.padEnd(17) + String(s.enCok).padEnd(14) + s.bostaSn.toFixed(0));
  }
  const a = kos(varislar("ani"));
  console.log(`\nani profilde soguk cagrilar gecikmeye ${(a.soguk * SOGUK / 1000).toFixed(0)} sn ekliyor; ` +
    `sicak cagri ${ISLEM} ms, soguk cagri ${ISLEM + SOGUK} ms — ${((ISLEM + SOGUK) / ISLEM).toFixed(2)} kat`);
}
pencere 1800 sn, isleme 400 ms, soguk ek 900 ms, omur 300 sn, pay 40

profil    cagri    soguk   soguk oran  ort gecikme   99. dilim   kuyruga giren  en uzun bekleme  en cok ornek  bosta ornek-sn
seyrek    18       2       %11.11      500 ms        1300 ms     0              0 ms             1             1722
duzenli   7242     9       %0.12       401 ms        400 ms      0              0 ms             8             10510
ani       7241     120     %1.66       419 ms        1300 ms     135            539 ms           40            38159

ani profilde soguk cagrilar gecikmeye 108 sn ekliyor; sicak cagri 400 ms, soguk cagri 1300 ms — 3.25 kat

Üç profil üç ayrı davranış gösterir. Düzenli trafikte soğuk oran %0,12’dir: istekler 250 ms arayla gelir, havuz sekiz örnekte oturur ve yalnız dokuz çağrı soğuk başlar. Seyrek trafikte oran %11,11’dir ve bu oran yükten değil çağrı seyrekliğinden gelir. Ani trafikte oran %1,66’dır ama asıl sayı başka sütundadır: 135 istek kuyruğa girer, en uzun bekleme 539 ms.

Kuyruk soğuk başlangıcın ikinci yüzüdür. Patlama başladığında havuz boştur; her yeni istek yeni bir örnek ister ve her örnek 900 ms kurulum harcar. Pay 40’a dayanınca istekler beklemeye başlar. Soğuk çağrı yalnız kendi gecikmesini artırmaz, havuzun dolmasını yavaşlatarak arkasındaki isteklere kuyruk oluşturur: ortalama 419 ms görünür, yüzde doksan dokuzuncu dilim 1.300 ms’dir.

Havuz Ömrü Taraması

Havuz ömrü devredilmiş bir karardır: bir örneğin ne kadar boşta tutulacağına sağlayıcı karar verir. Tarama ömrü sıfırdan 1800 saniyeye çıkarır.

// olcum-agi/omur-taramasi.mjs — havuz omru ve trafik profili degistikce soguk cagri orani (model)
import { PROFIL, varislar, kos } from "./sicak-havuz.mjs";

export const OMURLER = [0, 15, 30, 60, 120, 300, 600, 1800];   // saniye
export const ADLAR = Object.keys(PROFIL);

if (import.meta.url === `file://${process.argv[1]}`) {
  const varis = Object.fromEntries(ADLAR.map((a) => [a, varislar(a)]));
  console.log("havuz omru".padEnd(12) + ADLAR.map((a) => `${a}: soguk / bosta`.padEnd(24)).join("") +
    "ani: kuyruk / ort gecikme");
  const tablo = {};
  for (const o of OMURLER) {
    const s = Object.fromEntries(ADLAR.map((a) => [a, kos(varis[a], { omur: o * 1000 })]));
    tablo[o] = s;
    console.log(`${o} sn`.padEnd(12) +
      ADLAR.map((a) => `%${(s[a].oran * 100).toFixed(2)} / ${s[a].bostaSn.toFixed(0)}`.padEnd(24)).join("") +
      `${s.ani.kuyrukta} / ${s.ani.ortGecikme.toFixed(0)} ms`);
  }
  console.log("");
  for (const a of ADLAR) {
    const iyi = OMURLER.find((o) => tablo[o][a].oran < 0.01);
    const sifir = tablo[0][a], en = tablo[1800][a];
    console.log(`${a.padEnd(9)} omur 0'da %${(sifir.oran * 100).toFixed(1)} soguk ve ${sifir.bostaSn.toFixed(0)} bosta ornek-sn; ` +
      `omur 1800'de %${(en.oran * 100).toFixed(2)} ve ${en.bostaSn.toFixed(0)}; ` +
      (iyi === undefined ? "hicbir omurde %1'in altina inmiyor" : `%1'in altina ${iyi} sn omurde iniyor`));
  }
}
havuz omru  seyrek: soguk / bosta   duzenli: soguk / bosta  ani: soguk / bosta      ani: kuyruk / ort gecikme
0 sn        %100.00 / 0             %100.00 / 0             %49.99 / 0              3621 / 969 ms
15 sn       %88.89 / 266            %1.35 / 7651            %1.78 / 3819            135 / 420 ms
30 sn       %77.78 / 489            %0.65 / 8493            %1.73 / 5713            135 / 419 ms
60 sn       %72.22 / 895            %0.33 / 9208            %1.66 / 9359            135 / 419 ms
120 sn      %38.89 / 1364           %0.18 / 9883            %1.66 / 16559           135 / 419 ms
300 sn      %11.11 / 1722           %0.12 / 10510           %1.66 / 38159           135 / 419 ms
600 sn      %5.56 / 1781            %0.11 / 10873           %0.59 / 57609           47 / 407 ms
1800 sn     %5.56 / 1781            %0.11 / 10873           %0.55 / 69047           47 / 406 ms

seyrek    omur 0'da %100.0 soguk ve 0 bosta ornek-sn; omur 1800'de %5.56 ve 1781; hicbir omurde %1'in altina inmiyor
duzenli   omur 0'da %100.0 soguk ve 0 bosta ornek-sn; omur 1800'de %0.11 ve 10873; %1'in altina 30 sn omurde iniyor
ani       omur 0'da %50.0 soguk ve 0 bosta ornek-sn; omur 1800'de %0.55 ve 69047; %1'in altina 600 sn omurde iniyor

Tarama üç ayrı eğri verir. Düzenli trafikte 15 saniyelik ömür soğuk oranı %100’den %1,35’e indirir; ötesi kazandırmaz ama boşta örnek-saniyeyi 7.651’den 10.873’e çıkarır. Ani trafikte oran 15 saniyeden 300 saniyeye kadar hiç değişmez — %1,66’da takılır — ve 600 saniyede aniden %0,59’a düşer. Eşik tesadüf değildir: patlamalar arasındaki boşluk 540 saniyedir, ömür o boşluğu geçtiği anda havuz iki patlama arasında yaşar. Kuyruğa giren istek de aynı satırda 135’ten 47’ye iner.

Eşiğin fiyatı aynı satırdadır: boşta örnek-saniye 38.159’dan 57.609’a çıkar. Soğuk çağrıyı üçte bire indirmek boşta kapasiteyi yarı yarıya artırmakla ödenir.

Seyrek profil hiçbir ömürde %1’in altına inmez; 1800 saniyede bile oran %5,56’dır, çünkü on sekiz çağrının biri pencerenin ilkidir ve öncesinde havuz yoktur. Seyrek trafikte soğuk başlangıç bir ayar sorunu değil, trafiğin kendi özelliğidir.

Üç Azaltma Yolu

// olcum-agi/azaltma.mjs — soguk baslangici azaltmanin uc yolu ve her yolun bedeli (model)
import { SOGUK, ISLEM, PENCERE, varislar, kos } from "./sicak-havuz.mjs";

// [ad, kos secenekleri, bedelin cinsi]
export const YOL = [
  ["azaltma yok", {}, "—"],
  ["onceden isitma (16)", { isit: 16 }, "16 ornek 1800 sn bosta durur"],
  ["paket kucultme", { soguk: 350 }, "bagimliliklarin 3'u disari alinir"],
  ["baslatma tasinmasi", { soguk: 500, ekCagri: 40 }, "her cagriya 40 ms tembel yukleme"],
  ["kucultme + isitma", { soguk: 350, isit: 16 }, "ikisinin bedeli birlikte"],
];

if (import.meta.url === `file://${process.argv[1]}`) {
  const v = varislar("ani"), taban = kos(v);
  console.log(`ani profil, ${v.length} cagri, havuz omru 300 sn; sicak cagri ${ISLEM} ms`);
  console.log("\n" + "yol".padEnd(22) + "soguk".padEnd(8) + "soguk oran".padEnd(12) +
    "ort gecikme".padEnd(14) + "99. dilim".padEnd(12) + "kuyruga giren".padEnd(15) +
    "bosta ornek-sn".padEnd(16) + "maliyet".padEnd(10) + "gecikme kazanci");
  for (const [ad, sec] of YOL) {
    const s = kos(v, sec);
    console.log(ad.padEnd(22) + String(s.soguk).padEnd(8) + `%${(s.oran * 100).toFixed(2)}`.padEnd(12) +
      `${s.ortGecikme.toFixed(1)} ms`.padEnd(14) + `${s.g99.toFixed(0)} ms`.padEnd(12) +
      String(s.kuyrukta).padEnd(15) + s.bostaSn.toFixed(0).padEnd(16) + s.maliyet.toFixed(2).padEnd(10) +
      `${(taban.ortGecikme - s.ortGecikme).toFixed(1)} ms`);
  }
  console.log("\n" + "yol".padEnd(22) + "bedeli".padEnd(38) + "kazanilan ms basina ek maliyet");
  for (const [ad, sec, bedel] of YOL.slice(1)) {
    const s = kos(v, sec), kazanc = taban.ortGecikme - s.ortGecikme;
    console.log(ad.padEnd(22) + bedel.padEnd(38) +
      (kazanc > 0 ? ((s.maliyet - taban.maliyet) / kazanc).toFixed(3) : "kazanc yok"));
  }
  const esik = 40 / (SOGUK - 500);
  console.log(`baslatma tasinmasi ancak soguk oran %${(esik * 100).toFixed(0)}'un ustundeyse kazandirir: ` +
    `40 ms her cagriya, kazanilan 400 ms yalniz soguk cagriya duser — bu profilde oran %1.66`);
  const i = kos(v, { isit: 16 });
  console.log(`\nonceden isitma bostada gecen kapasiteyi ${taban.bostaSn.toFixed(0)} ornek-sn'den ` +
    `${i.bostaSn.toFixed(0)} ornek-sn'ye cikariyor; ${PENCERE / 1000} sn'lik pencerede ` +
    `${(i.maliyet - taban.maliyet).toFixed(2)} birim ek — soguk ekin kendisi ${SOGUK} ms`);
}
ani profil, 7241 cagri, havuz omru 300 sn; sicak cagri 400 ms

yol                   soguk   soguk oran  ort gecikme   99. dilim   kuyruga giren  bosta ornek-sn  maliyet   gecikme kazanci
azaltma yok           120     %1.66       418.9 ms      1300 ms     135            38159           11.13     0.0 ms
onceden isitma (16)   49      %0.68       406.1 ms      400 ms      0              42736           16.73     12.8 ms
paket kucultme        111     %1.53       405.4 ms      750 ms      0              35500           10.96     13.5 ms
baslatma tasinmasi    120     %1.66       448.5 ms      940 ms      22             38229           11.74     -29.7 ms
kucultme + isitma     43      %0.59       402.1 ms      400 ms      0              40933           16.66     16.8 ms

yol                   bedeli                                kazanilan ms basina ek maliyet
onceden isitma (16)   16 ornek 1800 sn bosta durur          0.438
paket kucultme        bagimliliklarin 3'u disari alinir     -0.013
baslatma tasinmasi    her cagriya 40 ms tembel yukleme      kazanc yok
kucultme + isitma     ikisinin bedeli birlikte              0.329
baslatma tasinmasi ancak soguk oran %10'un ustundeyse kazandirir: 40 ms her cagriya, kazanilan 400 ms yalniz soguk cagriya duser — bu profilde oran %1.66

onceden isitma bostada gecen kapasiteyi 38159 ornek-sn'den 42736 ornek-sn'ye cikariyor; 1800 sn'lik pencerede 5.60 birim ek — soguk ekin kendisi 900 ms

Üç yol üç ayrı cinsten bedel öder. Önceden ısıtma soğuk oranı %0,68’e, kuyruğu sıfıra indirir ve yüzde doksan dokuzuncu dilimi 1.300 ms’den 400 ms’ye çeker: havuzda hep on altı örnek beklediği için patlamanın ilk saniyesi soğuk değildir. Bedeli birinci dersin kaçındığı şeydir — boşta örnek-saniye 42.736’ya, fatura 11,13 birimden 16,73 birime çıkar, yani %50 artar.

Paket küçültme tek bedavaya benzeyen yoldur: soğuk ek 900 ms’den 350 ms’ye inince hem gecikme hem maliyet düşer. Ama bedel tabloda değildir — üç bağımlılık paketten çıkarılmıştır ve bir yerde karşılanması gerekir. Kısıtın etrafından dolaşmanın en sessiz biçimi budur.

Üçüncü yol zarar eder. Başlatma işinin taşınması soğuk eki 500 ms’ye indirir ama her çağrıya 40 ms tembel yükleme ekler; ortalama gecikme 29,7 ms artar ve yirmi iki istek kuyruğa girer. Son satır eşiği verir: 40 ms bütün çağrılara, kazanılan 400 ms yalnız soğuk çağrılara düşer, yani yol ancak soğuk oran %10’un üstündeyse kazandırır. Bu profilde oran %1,66, seyrek profilde %11,11’dir.

Özet

  • Soğuk çağrı 1.300 ms, sıcak çağrı 400 ms tutar: 3,25 kat. Ani profilde oran %1,66 olsa da 135 istek kuyruğa girer, en uzun bekleme 539 ms olur.
  • Havuz ömrü taramasında eşik trafiğin biçiminden çıkar: ani profilde oran 15–300 saniye arasında %1,66’da takılır, 600 saniyede %0,59’a iner, çünkü patlamalar arasındaki boşluk 540 saniyedir. Eşiğin bedeli aynı satırda yazılıdır: boşta örnek-saniye 38.159’dan 57.609’a çıkar.
  • Önceden ısıtma kuyruğu sıfıra indirir ve faturayı %50 artırır; paket küçültme ikisini de düşürür ama üç bağımlılığı paketten çıkarmayı ister.
  • Başlatma işinin taşınması bu profilde gecikmeyi 29,7 ms artırır; ancak soğuk oran %10’un üstündeyse kazandırır — azaltma yolunun kendisi bir eşiğe bağlıdır.

Sonraki Adım

Bu derste eşzamanlılık payı 40 sabit bir sayıydı ve kuyruğun nereden çıktığını açıkladı. Oysa tek başına duran bir sayı değildir: bellek seçimi işlemci payını, işlemci payı işlem süresini, işlem süresi de aynı payla kaç iş yapılacağını belirler.

Sonraki ders üç eşiği — bellek, süre ve eşzamanlılık — bir iş kümesine uygular ve kaç işin sığmadığını sayar. Bellek taranır, süre ile birim maliyetin ters yönde değiştiği ve en ucuz noktanın ortada çıktığı gösterilir. Eşzamanlılık sınırı aşıldığında kısma ile arkadaki kuyruk sayılır; sınırın hesap düzeyinde paylaşılması bir örnekle ölçülür.

İ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