İçeriğe geç
academia.sh

Ders 15 / 30

Kaynak İstekleri ve Sınırları

Yerleştirme kararının iki sayıya bağlanması: kaynak isteğinin zamanlayıcı defterini, sınırın koşum davranışını belirlemesi, aynı iş kümesinin üç istek ayarında yerleşen kapsül sayısı ve boş kapasiteyle karşılaştırılması, isteğin gerçek kullanımdan sapmasının taranması ve aşırı bildirimin israfı ile eksik bildirimin çakışmasının sayılması.

İçindekiler

Küme üzerinde koşan nesneler bildirildi: bir kapsül tanımlandı, kopyaları bir küme hâline getirildi, bir ad alanı içine alındı ve o ad alanının toplam kaynağı bir kotayla paylaştırıldı. Bütün bunlar boyunca tek bir soru hiç sorulmadı: hangi kapsül hangi düğüme düşecek. Kota bir tavan koyar, yerleştirmez. Kopya sayısı kaç tane olacağını söyler, nerede olacağını söylemez.

Yerleştirme, insandan sisteme geçen ilk mekanik karardır ve iki sayıya dayanır. Kapsül bildiriminde yan yana duran bu iki sayı ayrı yerlerde iş görür: kaynak isteği zamanlayıcının defterinde, sınır düğümdeki çalışma zamanında. Kaç düğüm gerektiği burada sorulmaz — o hesap, yük kısıtı ile arıza kısıtının büyüğü olarak, kapasite planlamasında yapıldı ve bu derste girdidir. Buradaki soru, elde belirli sayıda düğüm varken yerleşimin ne olacağıdır.

Ölçülen şey gerçek bir küme değil, node ile kurulan bir modeldir. İş yükü bölgesel ölçüm ağının (kurgu) servisleridir: okuma toplayıcı, doğrulayıcı, faturalama, iş emri ve gecelik toplu iş.

İstek Defteri Tutar, Sınır Kesme Yapar

Model üç düğüm ve on sekiz kapsülden oluşur. Zamanlayıcı ilk uyan düğüme yerleştirir ve yalnız bildirilen isteği görür; gerçek kullanımı hiç görmez. Gerçek kullanım kendi yazdığımız üretecin tohumundan türer ve tabanın yüzde 35 bandında dağılır.

// zamanlama/istek.mjs — istek ve sinirin yerlestirmeye etkisi. Kurulan sey bir MODELDIR;
// gercek kume kosturulmaz. Is yuku bolgesel olcum aginin (kurgu) servisleridir.
export const DUGUM = { islemci: 3000, bellek: 4096 };  // ZO1: dugum basina ayrilabilir kapasite
export const DUGUM_SAYISI = 3;

// ZO2: servis, kapsul sayisi, taban islemci birimi, taban bellek (MiB)
const SERVIS = [
  ["okuma-toplayici", 6, 420, 384], ["dogrulayici", 4, 650, 704],
  ["faturalama", 3, 300, 512], ["is-emri", 3, 180, 256], ["gecelik-toplu", 2, 900, 1408],
];
const TOHUM = 20260801;                       // uretec kendi yazildi, tohum gorunur

export function uretec(tohum = TOHUM) {
  let s = tohum % 2147483647;
  return () => (s = (s * 48271) % 2147483647) / 2147483647;
}

// ZO3: gercek kullanim tabanin ±%35 bandinda; olculur, bildirilmez
export function isYuku() {
  const r = uretec(), k = [];
  for (const [ad, adet, ci, mi] of SERVIS)
    for (let i = 0; i < adet; i++) {
      const sapma = 0.65 + 0.7 * r();
      k.push({ ad: `${ad}-${i + 1}`, tabanC: ci, tabanM: mi,
               gercekC: Math.round(ci * sapma), gercekM: Math.round(mi * sapma) });
    }
  return k;
}

// Zamanlayici yalniz BILDIRILEN istegi gorur; gercek kullanimi hic gormez.
export function yerlestir(kapsuller, n = DUGUM_SAYISI) {
  const dugumler = Array.from({ length: n }, () => ({ isC: 0, isM: 0, kapsul: [] }));
  const yerlesmeyen = [];
  for (const k of kapsuller) {
    const d = dugumler.find((d) => d.isC + k.istekC <= DUGUM.islemci &&
                                   d.isM + k.istekM <= DUGUM.bellek);
    if (d === undefined) { yerlesmeyen.push(k); continue; }
    d.isC += k.istekC; d.isM += k.istekM; d.kapsul.push(k);
  }
  return { dugumler, yerlesmeyen };
}

// ZO4: sinir = istek x 1,25. Islemci sinirini asan kisitlanir, bellek sinirini asan sonlandirilir.
export const SINIR_CARPANI = 1.25;

export function olc(kapsuller, n = DUGUM_SAYISI) {
  const { dugumler, yerlesmeyen } = yerlestir(kapsuller, n);
  let israf = 0, cakisma = 0, kisitlanan = 0, sonlanan = 0, yerlesen = 0;
  for (const d of dugumler) {
    const gC = d.kapsul.reduce((t, k) => t + k.gercekC, 0);
    d.gercekC = gC;
    cakisma += Math.max(0, gC - DUGUM.islemci);
    yerlesen += d.kapsul.length;
    for (const k of d.kapsul) {
      israf += Math.max(0, k.istekC - k.gercekC);
      if (k.sinirC > 0 && k.gercekC > k.sinirC) kisitlanan++;
      if (k.sinirM > 0 && k.gercekM > k.sinirM) sonlanan++;
    }
  }
  return { dugumler, yerlesen, yerlesmeyen: yerlesmeyen.length, israf, cakisma,
           kisitlanan, sonlanan,
           bosIstek: dugumler.reduce((t, d) => t + (DUGUM.islemci - d.isC), 0) };
}

export function ayarla(kapsuller, kip) {
  return kapsuller.map((k) => {
    const c = kip === "yok" ? 0 : kip === "gercekci" ? k.tabanC : k.tabanC * 2;
    const m = kip === "yok" ? 0 : kip === "gercekci" ? k.tabanM : k.tabanM * 2;
    return { ...k, istekC: c, istekM: m,
             sinirC: kip === "yok" ? 0 : Math.round(c * SINIR_CARPANI),
             sinirM: kip === "yok" ? 0 : Math.round(m * SINIR_CARPANI) };
  });
}

if (process.argv[1].endsWith("istek.mjs")) {
  const k = isYuku();
  const topC = k.reduce((t, x) => t + x.gercekC, 0), topM = k.reduce((t, x) => t + x.gercekM, 0);
  console.log(`model: ${k.length} kapsul, ${DUGUM_SAYISI} dugum x ${DUGUM.islemci} islemci ` +
    `birimi / ${DUGUM.bellek} MiB = ${DUGUM_SAYISI * DUGUM.islemci} / ` +
    `${DUGUM_SAYISI * DUGUM.bellek}`);
  console.log(`gercek toplam kullanim ${topC} islemci birimi, ${topM} MiB (tohum ${TOHUM})\n`);
  const bas = (s) => s.padStart(13);
  console.log(`${"ayar".padEnd(18)}${bas("yerlesen")}${bas("yerlesmeyen")}${bas("bos istek")}` +
    `${bas("israf")}${bas("cakisma")}${bas("kisitlanan")}${bas("sonlanan")}`);
  for (const kip of ["yok", "gercekci", "sisirilmis"]) {
    const o = olc(ayarla(k, kip));
    console.log(`${kip.padEnd(18)}${bas(String(o.yerlesen))}${bas(String(o.yerlesmeyen))}` +
      `${bas(String(o.bosIstek))}${bas(String(o.israf))}${bas(String(o.cakisma))}` +
      `${bas(String(o.kisitlanan))}${bas(String(o.sonlanan))}`);
  }
  console.log(`\ndugum basina gercek doluluk (islemci birimi / ${DUGUM.islemci}):`);
  for (const kip of ["yok", "gercekci", "sisirilmis"]) {
    const o = olc(ayarla(k, kip));
    console.log(`  ${kip.padEnd(12)}` + o.dugumler.map((d, i) =>
      `d${i}: ${d.kapsul.length} kapsul %${((d.gercekC / DUGUM.islemci) * 100).toFixed(0)}`)
      .join("   "));
  }
  console.log(`\nkarar icin gereken bilgi: ${k.length} kapsul x 2 bildirim = ${k.length * 2}, ` +
    `${DUGUM_SAYISI} dugum x 2 olcum = ${DUGUM_SAYISI * 2}, toplam ${k.length * 2 + DUGUM_SAYISI * 2}`);
  console.log(`zamanlayicinin gormedigi kalem: gercek kullanim (${k.length} kapsul x 2 = ${k.length * 2})`);
}
model: 18 kapsul, 3 dugum x 3000 islemci birimi / 4096 MiB = 9000 / 12288
gercek toplam kullanim 8503 islemci birimi, 10193 MiB (tohum 20260801)

ayar                   yerlesen  yerlesmeyen    bos istek        israf      cakisma   kisitlanan     sonlanan
yok                          18            0         9000            0         5503            0            0
gercekci                     18            0          640          675          557            1            1
sisirilmis                   11            7          280         3934            0            0            0

dugum basina gercek doluluk (islemci birimi / 3000):
  yok         d0: 18 kapsul %283   d1: 0 kapsul %0   d2: 0 kapsul %0
  gercekci    d0: 8 kapsul %108   d1: 5 kapsul %110   d2: 5 kapsul %65
  sisirilmis  d0: 4 kapsul %49   d1: 4 kapsul %56   d2: 3 kapsul %55

karar icin gereken bilgi: 18 kapsul x 2 bildirim = 36, 3 dugum x 2 olcum = 6, toplam 42
zamanlayicinin gormedigi kalem: gercek kullanim (18 kapsul x 2 = 36)

Üç Ayar, Üç Ayrı Başarısızlık

Üç satır üç ayrı dünya kuruyor. İstek yok ayarında defterdeki her düğüm boştur, bu yüzden on sekiz kapsülün tamamı ilk düğüme yığılır: zamanlayıcı hiç hata yapmadığını düşünürken düğümün gerçek doluluğu yüzde 283 olur ve 5.503 birimlik çakışma doğar. Kaynak paylaşımı burada işletim sistemine kalır ve kimin yavaşladığı bildirimden okunamaz.

Gerçekçi istek ayarında on sekiz kapsül üç düğüme dağılır, boş istek 640 birime iner. Ayarın kusursuz olmadığı iki sütunda görünür: gerçek kullanım bildirimin altında kaldığı için 675 birim rezerve edilip kullanılmıyor, üstüne çıktığı yerlerde 557 birimlik çakışma kalıyor. Bir kapsül işlemci sınırını aştığı için kısıtlanıyor, bir kapsül bellek sınırını aştığı için sonlandırılıyor. Sınırın yaptırımı yerleştirmeden bağımsızdır: iki kapsül de yerleşmiş, ikisi de defterde uygundur.

Şişirilmiş istek ayarında hiçbir çakışma ve hiçbir kesme yoktur; bedeli yedi kapsülün hiç yerleşmemesidir. Düğümler gerçekte yarı boş çalışır (yüzde 49, 56, 55) ve 3.934 birim rezerve edilip kullanılmadan durur. Bu ayar bir güvenlik ayarı gibi görünür, bir kapasite kaybıdır.

Sapma Taranınca İki Bedel Ayrışıyor

Bildirim gerçek kullanımın katı olarak yazılıp taranınca iki yönün bedeli ayrı ayrı sayılabilir. Aynı tarama, bildirimin bir kez yapılıp yerinde kalmasının ve sınır çarpanı seçiminin sonucunu da verir. Katsayı bir bilgi kalitesi ölçüsü gibi okunabilir: birden uzaklaştıkça bildirimin gerçeği ne kadar yanlış anlattığı büyür.

// zamanlama/sapma.mjs — istegin gercek kullanimdan sapmasi taranir: asiri bildirimin israfi,
// eksik bildirimin cakismasi. Model ve is yuku onceki dosyadan alinir.
import { DUGUM, DUGUM_SAYISI, SINIR_CARPANI, isYuku, olc } from "./istek.mjs";

const kapsuller = isYuku();
const KAPASITE = DUGUM_SAYISI * DUGUM.islemci;

// Istek = gercek kullanim x katsayi. Katsayi 1 ise bildirim kusursuzdur.
const bildir = (k, kat, buyume = 1) => k.map((x) => {
  const c = Math.round(x.gercekC * kat), m = Math.round(x.gercekM * kat);
  return { ...x, istekC: c, istekM: m,
           gercekC: Math.round(x.gercekC * buyume), gercekM: Math.round(x.gercekM * buyume),
           sinirC: Math.round(c * SINIR_CARPANI), sinirM: Math.round(m * SINIR_CARPANI) };
});

const s = (x) => String(x).padStart(12);
console.log(`istegin gercek kullanimdan sapmasi (${kapsuller.length} kapsul, kapasite ${KAPASITE}):`);
console.log(`${"katsayi".padEnd(10)}${s("yerlesen")}${s("yerlesmeyen")}${s("israf")}` +
  `${s("cakisma")}${s("kisitlanan")}${s("sonlanan")}`);
for (const kat of [0.5, 0.75, 0.9, 1.0, 1.25, 1.5, 2.0]) {
  const o = olc(bildir(kapsuller, kat));
  console.log(`${("x" + kat.toFixed(2)).padEnd(10)}${s(o.yerlesen)}${s(o.yerlesmeyen)}` +
    `${s(o.israf)}${s(o.cakisma)}${s(o.kisitlanan)}${s(o.sonlanan)}`);
}

// Bildirim bir kez yapilir, kullanim buyur: eskiyen bildirimin bedeli.
console.log(`\nbildirim x1,00'de sabit kalirken gercek kullanim buyurse (ZO5):`);
console.log(`${"buyume".padEnd(10)}${s("yerlesen")}${s("cakisma")}${s("kisitlanan")}${s("sonlanan")}`);
for (const b of [1.0, 1.1, 1.2, 1.3, 1.5]) {
  const o = olc(bildir(kapsuller, 1.0, b));
  console.log(`${("%" + ((b - 1) * 100).toFixed(0)).padEnd(10)}${s(o.yerlesen)}${s(o.cakisma)}` +
    `${s(o.kisitlanan)}${s(o.sonlanan)}`);
}

// ZO6: kisa sureli tepede kullanim %30 artiyor. Sinir carpani taranir.
const TEPE = 1.3;
console.log(`\nsinir carpani (istek x1,00 bildirim, tepede kullanim %30 yuksek):`);
console.log(`${"carpan".padEnd(10)}${s("kisitlanan")}${s("sonlanan")}${s("cakisma")}${s("sinir topl.")}`);
for (const c of [1.0, 1.1, 1.25, 1.5, 2.0]) {
  const k2 = kapsuller.map((x) => ({ ...x, istekC: x.gercekC, istekM: x.gercekM,
    gercekC: Math.round(x.gercekC * TEPE), gercekM: Math.round(x.gercekM * TEPE),
    sinirC: Math.round(x.gercekC * c), sinirM: Math.round(x.gercekM * c) }));
  const o = olc(k2);
  console.log(`${("x" + c.toFixed(2)).padEnd(10)}${s(o.kisitlanan)}${s(o.sonlanan)}${s(o.cakisma)}` +
    `${s(k2.reduce((t, x) => t + x.sinirC, 0))}`);
}
console.log(`\nsinir toplami x2,00 carpanda ${(kapsuller.reduce((t, x) => t + x.gercekC, 0) * 2 /
  KAPASITE).toFixed(2)} kat kapasite; sinir bir rezervasyon degildir, bir tavandir`);
istegin gercek kullanimdan sapmasi (18 kapsul, kapasite 9000):
katsayi       yerlesen yerlesmeyen       israf     cakisma  kisitlanan    sonlanan
x0.50               18           0           0        2965          18          18
x0.75               18           0           0        1916          18          18
x0.90               18           0           0         557           0           0
x1.00               17           1           0           0           0           0
x1.25               14           4        1720           0           0           0
x1.50               13           5        2876           0           0           0
x2.00                9           9        4322           0           0           0

bildirim x1,00'de sabit kalirken gercek kullanim buyurse (ZO5):
buyume        yerlesen     cakisma  kisitlanan    sonlanan
%0                  17           0           0           0
%10                 17         470           0           0
%20                 17        1058           0           0
%30                 17        1646          17          17
%50                 17        2879          17          17

sinir carpani (istek x1,00 bildirim, tepede kullanim %30 yuksek):
carpan      kisitlanan    sonlanan     cakisma sinir topl.
x1.00               17          17        1646        8503
x1.10               17          17        1646        9355
x1.25               17          17        1646       10630
x1.50                0           0        1646       12760
x2.00                0           0        1646       17006

sinir toplami x2,00 carpanda 1.89 kat kapasite; sinir bir rezervasyon degildir, bir tavandir

Aşırı Bildirimin İsrafı, Eksik Bildirimin Çakışması

Tarama simetrik değildir. Katsayı 1’in altına indikçe kapsüllerin tamamı yerleşir ve fatura çakışmada birikir: yarım bildirimde 2.965 birim, dörtte üç bildirimde 1.916 birim, ve on sekiz kapsülün on sekizi hem kısıtlanır hem sonlandırılır. Katsayı 1’in üstüne çıkınca çakışma sıfırlanır, fatura bu kez yerleşmeyen kapsüle ve israfa geçer: bir buçuk katta beş kapsül yerleşemez ve 2.876 birim boşta durur, iki katta dokuz kapsül yerleşemez.

Kusursuz bildirim satırı da bir şey öğretiyor. Katsayı tam 1 olduğunda çakışma sıfırdır, israf sıfırdır, ama yine bir kapsül yerleşemiyor. Bunun nedeni bilgi eksikliği değil, ilk uyan düğüme yerleştiren kuralın geriye bakmamasıdır: kalan boşluklar tek tek yeterli olmadığı için parçalanma kalır. Bilgi kusursuz olsa bile yerleştirme kuralı bir kayıp üretir.

İkinci tablo bildirimin eskimesini ölçüyor. Bildirim yerinde kalırken gerçek kullanım yüzde 10 büyüdüğünde 470 birimlik çakışma, yüzde 20’de 1.058 birim doğuyor; yüzde 30’da on yedi kapsül aynı anda hem kısıtlanıyor hem sonlandırılıyor. Bildirim bir ölçüm değil bir beyandır ve ölçüm gibi tazelenmediği sürece sistemin elindeki en eski bilgidir.

Üçüncü tablo sınırın ne olmadığını gösteriyor. Çarpan 1’den 2’ye çıkarıldığında kısıtlanan kapsül sayısı on yediden sıfıra iner, çakışma 1.646 birimde hiç değişmez. Sınır yalnız tek kapsülün tepesini keser; düğümün toplamını korumaz. Sınırların toplamı iki katı çarpanda kümenin kapasitesinin 1,89 katına çıkabilir, çünkü sınır bir rezervasyon değil bir tavandır. Düğüm toplamını koruyan tek sayı istektir.

Bilginin Maliyeti ve Görülmeyen Kalem

Yerleştirme kararı için sistemin elinde kırk iki bilgi kalemi vardır: on sekiz kapsülün ikişer bildirimi (otuz altı kalem) ve üç düğümün ikişer ölçümü (altı kalem). Bu kalemlerin maliyeti eşit değildir. Altı ölçüm düğümdeki aracı süreçten düzenli gelir ve tazedir. Otuz altı bildirim bir kez yazılır, kimse doğrulamaz ve yük değiştikçe sessizce yanlışlaşır.

Bu kalemi ölçmek imkânsız değildir, bedellidir: her kapsül için sürekli bir kullanım serisi toplanması, saklanması ve bildirimle karşılaştırılması gerekir. Bu ders o seriyi zamanlayıcıya vermez; verildiğinde ne olduğu bu konunun son iki dersinin konusudur.

Kırk üçüncü kalem hiç yoktur: gerçek kullanım. Zamanlayıcı bu dersteki hiçbir tabloda gerçek kullanımı görmez. Yanlış kararların üçü de aynı boşluktan çıkar — istek yok ayarında on sekiz kapsülü tek düğüme yığmak, gerçekçi ayarda 557 birimlik çakışmayı fark etmemek, şişirilmiş ayarda yarı boş düğümler dururken yedi kapsülü bekletmek. Üçünde de zamanlayıcının defteri tutarlıdır; tutarsız olan defter ile düğümdür.

Özet

  • Kaynak isteği zamanlayıcının defterini, sınır düğümdeki koşumu belirler; bir kapsül yerleşip yine kısıtlanabilir ya da sonlandırılabilir.
  • Üç ayarın bedelleri ayrıdır: istek yok ayarında on sekiz kapsül tek düğümde ve yüzde 283 doluluk, gerçekçi ayarda 640 birim boş istek ile 557 birim çakışma, şişirilmiş ayarda yedi yerleşmeyen kapsül ile 3.934 birim israf.
  • Eksik bildirimin bedeli çakışma ve kesmedir (yarım bildirimde 2.965 birim, on sekiz kapsülün tamamı kısıtlanır); aşırı bildirimin bedeli yerleşmeyen kapsül ve israftır (iki katta dokuz kapsül yerleşemez, 4.322 birim boşta durur).
  • Kusursuz bildirimde bile bir kapsül yerleşemiyor: bilgi tam olsa da ilk uyan düğüme yerleştiren kural parçalanma üretir.
  • Sınır çarpanını dört katına çıkarmak kısıtlanan kapsülü on yediden sıfıra indirir, düğümdeki 1.646 birimlik çakışmayı hiç değiştirmez; sınırların toplamı kapasitenin 1,89 katı olabilir.
  • Karar kırk iki bilgi kalemine dayanıyor, otuz altısı tazelenmeyen bildirim; kırk üçüncü kalem olan gerçek kullanım hiç görünmüyor ve üç yanlış kararın da kaynağı bu.

Sonraki Adım

Bu dersin zamanlayıcısı tek bir soru soruyor: kalan istek yeter mi. Yerleşim kararının başka yanları da vardır ve hiçbiri kapasiteyle ilgili değildir. Doğrulayıcının hızlı diski olan düğümlerde koşması, aynı servisin kopyalarının aynı düğüme yığılmaması, bir bölge kaybında ayakta kalan kopya kalmasının garanti edilmesi — bunların her biri zamanlayıcıya yeni bir kısıt ekler ve uygun düğüm kümesini daraltır. Sonraki ders zamanlayıcıyı bir kısıt çözücü olarak yazar ve kısıt eklendikçe kaç kapsülün yerleşemez hâle geldiğini sayar.

İ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