İçeriğe geç
academia.sh

Ders 10 / 21

Temel İmaj Seçimi

Üç temel imaj adayı tür nitelemesiyle ölçülür: bayt, taşınan ikili ve kütüphane sayısı, kabuk ile paket yöneticisinin varlığı sayılır; temel güncellendiğinde kaç katmanın gerçekten değiştiği hesaplanır ve küçük temelin gizli bedeli hata ayıklamada atılan ek adım ile kırılan bağımlılık baytıyla ölçülür.

İçindekiler

Önceki ders derleme araçlarını çıktıdan ayırdı: derleyici, geliştirme başlıkları ve ara dosyalar son çıktının dışında kaldı, çıktı küçüldü. Ama küçülen şey üst katmanlardı. Son aşama hâlâ bir temelin üzerine kurulur ve o temel, imajın içinde yazılmayan tek bölümdür — ilk yönergeden önce gelir, dosyalarını başkası derlemiştir, güncelleme çizelgesini başkası belirler.

Bu ders o tabanı ölçer. Soru “hangisi iyi” değil; üç aday tür için aynı niceliklerin — bayt, taşınan ikili, güncelleme yükü — ne çıktığı ve küçük olanın hangi bedeli görünmeyen yere ittiğidir.

IM25. Adaylar ürün olarak değil tür olarak anılır: tam donanımlı temel, küçültülmüş temel, tek ikili temel. IM26. Envanter sayıları kendi üretecimizden gelir; tohum 20260518 görünürdür ve sayılar gerçek bir ölçüm değil, büyüklük mertebesidir. IM27. Üstteki uygulama katmanı üç adayda da aynıdır: bölgesel ölçüm ağının — su sayaçlarından okuma toplayan kurgu yazılımın — okuma toplayıcı servisi, 24 MB.

Temelin İçinde Ne Var

Temel imaj, ortamda kurulu olan şeyleri çıktının içine alma işinin büyük kısmını yapar: kütüphaneler, sertifika deposu, saat dilimi verisi, kabuk. Aday türleri arasındaki fark, bu kümenin nerede kesildiğidir. Tam donanımlı temel genel amaçlı bir işletim ortamının paket kümesini taşır; kabuk, paket yöneticisi, süreç ve ağ araçları içinde gelir. Küçültülmüş temel aynı kümeyi tek bir çok işlevli ikiliye ve zorunlu kütüphanelere indirir, ama kabuğu ve paket yöneticisini bırakır. Tek ikili temel yalnız uygulamanın bağlandığı kütüphaneleri, sertifikaları ve saat dilimi verisini taşır.

// olcum-agi/temel.mjs — uc temel imaj adayinin envanteri (model; urun degil tur)
export const uretec = (tohum) => () =>
  (tohum = (tohum * 1103515245 + 12345) % 2147483648) / 2147483648;

// [adet, alt bayt, ust bayt]. Sayilar ureteçten gelir; buyukluk mertebesidir.
export const ADAYLAR = [
  { ad: "tam donanimli", ikili: [480, 8e3, 220e3], kutuphane: [310, 12e3, 240e3],
    veri: [2400, 1e3, 14e3], kabuk: true, paket: true, bilesen: 148 },
  { ad: "kucultulmus", ikili: [140, 3e3, 60e3], kutuphane: [95, 8e3, 120e3],
    veri: [120, 1e3, 9e3], kabuk: true, paket: true, bilesen: 31 },
  { ad: "tek ikili", ikili: [0, 0, 0], kutuphane: [6, 30e3, 900e3],
    veri: [40, 1e3, 30e3], kabuk: false, paket: false, bilesen: 6 },
];

export const UYGULAMA = 24_000_000; // okuma toplayici servisi; uc adayda da ayni

export const envanter = (aday, tohum = 20260518) => {
  const r = uretec(tohum);
  const grup = ([n, alt, ust]) => {
    let bayt = 0;
    for (let i = 0; i < n; i++) bayt += alt + Math.round(r() * (ust - alt));
    return { n, bayt };
  };
  const i = grup(aday.ikili), k = grup(aday.kutuphane), v = grup(aday.veri);
  return { ...aday, i, k, v, dosya: i.n + k.n + v.n, bayt: i.bayt + k.bayt + v.bayt };
};

export const mb = (b) => (b / 1e6).toFixed(1) + " MB";

// Asagisi yalniz bu dosya dogrudan kosturuldugunda calisir; digerleri modul olarak alir.
if (import.meta.url === `file://${process.argv[1]}`) {
  const satirlar = ADAYLAR.map((a) => envanter(a));
  console.log("aday".padEnd(15) + "dosya".padEnd(8) + "ikili".padEnd(7) +
    "kutuphane".padEnd(11) + "kabuk".padEnd(7) + "paket yon.".padEnd(12) +
    "temel".padEnd(10) + "imaj");
  for (const s of satirlar) {
    console.log(s.ad.padEnd(15) + String(s.dosya).padEnd(8) + String(s.i.n).padEnd(7) +
      String(s.k.n).padEnd(11) + (s.kabuk ? "var" : "yok").padEnd(7) +
      (s.paket ? "var" : "yok").padEnd(12) + mb(s.bayt).padEnd(10) +
      mb(s.bayt + UYGULAMA));
  }
  const [tam, kucuk, tek] = satirlar;
  console.log(`\ntemelin imaj icindeki payi: ${(100 * tam.bayt / (tam.bayt + UYGULAMA)).toFixed(0)}% / ` +
    `${(100 * kucuk.bayt / (kucuk.bayt + UYGULAMA)).toFixed(0)}% / ` +
    `${(100 * tek.bayt / (tek.bayt + UYGULAMA)).toFixed(0)}%`);
  console.log(`imaj icinde calistirilabilir dosya: ${tam.i.n} / ${kucuk.i.n} / ${tek.i.n}`);
  console.log(`guncelleme izlenecek bilesen: ${tam.bilesen} / ${kucuk.bilesen} / ${tek.bilesen}`);
}
aday           dosya   ikili  kutuphane  kabuk  paket yon.  temel     imaj
tam donanimli  3190    480    310        var    var         111.1 MB  135.1 MB
kucultulmus    355     140    95         var    var         10.5 MB   34.5 MB
tek ikili      46      0      6          yok    yok         4.1 MB    28.1 MB

temelin imaj icindeki payi: 82% / 30% / 14%
imaj icinde calistirilabilir dosya: 480 / 140 / 0
guncelleme izlenecek bilesen: 148 / 31 / 6

Aynı uygulama, üç temelin üzerinde 135,1 MB ile 28,1 MB arasında değişen bir çıktı verir. Tam donanımlı temelde imajın yüzde 82’si yazılmamış bölümdür: temel tek başına 3190 dosya taşır ve bunların hiçbiri bu iş için yazılmamıştır.

İkinci satır bayt değildir. İmajın içinde çalıştırılabilir 480 dosya bulunması, bir kod çalıştırma açığı bulunduğunda hazır bekleyen araç sayısıdır — dosya indirici, arşivleyici, derleyici, ağ istemcisi. Saldırı yüzeyi bu sayıya eşit değildir, ama bu sayı onun üst sınırıdır ve tek ikili temelde sıfırdır.

Üç adayın hiçbirinin değiştirmediği bir şey vardır: çekirdek. Temel imaj kullanıcı alanındaki dosyaları taşır, çekirdek arayüzünü taşımaz; üç aday da altında duran çekirdeğin sunduğu sistem çağrısı kümesine bağlıdır ve o küme imajın içinde değildir. Tek ikili temelin 46 dosyası, tam donanımlı temelin 3190 dosyasıyla aynı çağrı yüzeyine erişir. Boyut tablosu bu yüzden yalıtımın tamamını ölçmez — yalnız kullanıcı alanının ne kadarının çıktıya alındığını ölçer.

Ortamdan çıkarılan fark burada sayılır: kurulu paketler ve kütüphane sürümleri artık ortamda değil, çıktının içindedir — 148, 31 ya da 6 bileşen olarak. Fark yok olmadı; yalnız yer değiştirdi ve başka bir yayıncının çizelgesine bağlandı. Bir sonraki bölüm o çizelgenin bedelini sayar.

Güncelleme Geldiğinde Kaç Katman Değişir

Bileşen sayısı yalnız bayt değil, olay sıklığı demektir. Her bileşen kendi güncellemelerini üretir ve temel yayıncısı bunları yeni bir temel sürümü olarak yayımlar. Temel katman değiştiğinde imajın yeniden derlenmesi gerekir; asıl soru, üstteki katmanların da değişip değişmediğidir.

IM28. Bileşen başına yılda ortalama 0,9 güvenlik güncellemesi düşer ve çalışan makine sayısı 12’dir; ikisi de kurgudur. IM29. İmaj dört katmandır: temel, bağımlılıklar, uygulama, yapılandırma. Yeniden derleme iki disiplinle ölçülür — belirlenimci derleme katmanlara hiçbir değişken damga koymaz, damgalı derleme her yeniden derlenen katmana koşum zamanını yazar.

// olcum-agi/guncelleme.mjs — temel guncellendiginde kac katman gercekten degisiyor (model)
import { createHash } from "node:crypto";
import { ADAYLAR, envanter, mb } from "./temel.mjs";

const ozet = (s) => createHash("sha256").update(s).digest("hex").slice(0, 10);
const gb = (b) => (b / 1e9).toFixed(1) + " GB";
const DUGUM = 12;              // olcum agindaki calisan makine sayisi (kurgu)
const YILLIK_ORAN = 0.9;       // bilesen basina yillik guvenlik guncellemesi (kurgu)

// Imaj dort katmandir: temel + uygulamanin uc katmani. Ust uc katman uc adayda ayni.
const UST = [["bagimliliklar", 16.0e6], ["uygulama", 7.2e6], ["yapilandirma", 0.8e6]];

// damga=null: belirlenimci yeniden derleme. damga=<deger>: her katmana zaman damgasi girer.
const katmanlar = (temelSurum, temelBayt, damga) => [
  { ad: "temel", bayt: temelBayt, ozet: ozet(`temel@${temelSurum}`) },
  ...UST.map(([ad, bayt]) => ({ ad, bayt, ozet: ozet(`${ad}@v1${damga ?? ""}`) })),
];

console.log("aday".padEnd(15) + "yillik guncelleme".padEnd(19) + "degisen katman".padEnd(18) +
  "degisen bayt".padEnd(14) + "yillik cekme");
for (const aday of ADAYLAR) {
  const e = envanter(aday);
  const eski = katmanlar("2026.05", e.bayt, null);
  for (const [etiket, damga] of [["belirlenimci", null], ["damgali", "-b2"]]) {
    const yeni = katmanlar("2026.06", e.bayt, damga);
    const degisen = yeni.filter((k, i) => k.ozet !== eski[i].ozet);
    const bayt = degisen.reduce((t, k) => t + k.bayt, 0);
    const yillik = Math.round(aday.bilesen * YILLIK_ORAN);
    console.log((etiket === "belirlenimci" ? aday.ad : "").padEnd(15) +
      (etiket === "belirlenimci" ? `${yillik} kez` : "").padEnd(19) +
      `${degisen.length}/4 ${etiket}`.padEnd(18) + mb(bayt).padEnd(14) +
      gb(yillik * bayt * DUGUM));
  }
}
console.log(`\nyillik cekme = yillik guncelleme x degisen bayt x ${DUGUM} dugum`);
aday           yillik guncelleme  degisen katman    degisen bayt  yillik cekme
tam donanimli  133 kez            1/4 belirlenimci  111.1 MB      177.4 GB
                                  4/4 damgali       135.1 MB      215.7 GB
kucultulmus    28 kez             1/4 belirlenimci  10.5 MB       3.5 GB
                                  4/4 damgali       34.5 MB       11.6 GB
tek ikili      5 kez              1/4 belirlenimci  4.1 MB        0.2 GB
                                  4/4 damgali       28.1 MB       1.7 GB

yillik cekme = yillik guncelleme x degisen bayt x 12 dugum

Tablonun iki sütunu birlikte okunmalıdır. Belirlenimci derlemede temel güncellemesi dört katmanın yalnız birini değiştirir: üstteki üç katmanın içeriği aynı kaldığı için özetleri de aynı kalır ve çekmede atlanır. Damgalı derlemede aynı güncelleme dörtte dördünü değiştirir, çünkü içerik aynı olsa bile katmana yazılan koşum zamanı özeti kaydırır. Fark tam donanımlı temelde yıllık 38,3 GB, tek ikili temelde 1,5 GB’dir. Belirlenimcilik temelin bir özelliği değil, derleme adımının disiplinidir — temel ne kadar küçük olursa olsun, damga koyan bir derleme her güncellemede imajın tamamını yeniden dağıtır.

Yıllık çekme sütunu asıl açıklığı gösterir: tam donanımlı temelde 177,4 GB, tek ikili temelde 0,2 GB. Aradaki büyüklüğün kaynağı bayt kadar sıklıktır: tam donanımlı temel yılda 133 kez, tek ikili temel 5 kez güncellenir ve ikincisinin izlemesi gereken bileşen sayısı 6’dır. Küçük temelin en somut kazancı burada görünür — imajın boyutu değil, güncelleme yüzeyinin boyutu.

Bu, yalıtımın delindiği yerlerden birini de yazar: temel imaj çıktının içine alınmıştır ama üretimi dışarıdadır. Yılda 133 kez, kararı verilmeyen bir değişiklik çıktının en alt katmanına girer. Sürüm sabitlenerek durdurulabilir — o zaman da güvenlik güncellemeleri girmez.

Küçük Temelin Gizli Bedeli

Küçük temelin bedeli boyut tablosunda görünmez; iki yerde görünür. Birincisi bir olay sırasındadır: kabuk, süreç listeleyici ya da ağ aracı imajın içinde yoksa, o araçla bakılacak soruya yerinde bakılamaz. İkincisi derleme sırasındadır: temelde bulunmayan bir kütüphane, imaja elle eklenmek zorundadır.

IM30. Sekiz olay türü, her birinin yerinde bakılabilmesi için gereken araç kümesi ve servisin dokuz yerel bağımlılığı kurgudur. Araç eksikse ek adım sayısı sabit bir kurala bağlanır: paket yöneticisi varsa 2 (kurulum ve sonrasında imajın temizlenmesi), yoksa 4 (yardımcı bir konteyner hazırlama, ad alanını paylaştırma, çıktıyı dışarı kopyalama, yeniden çalıştırma). Her bağımlılık ancak belli bir yalınlığa kadar temelde hazır gelir.

// olcum-agi/bedel.mjs — kucuk temelin gizli bedeli: hata ayiklama adimi ve uyumluluk (model)
import { ADAYLAR, envanter, UYGULAMA, mb } from "./temel.mjs";

// Adaylarin tasidigi arac kumesi (kurgu, tur adlariyla).
const ARAC = {
  "tam donanimli": ["kabuk", "paket", "surec", "ag", "dosya", "arama"],
  "kucultulmus": ["kabuk", "paket", "surec", "dosya", "arama"],
  "tek ikili": [],
};
// Olcum agindaki sekiz olay turu ve yerinde bakmak icin gereken arac (kurgu).
const OLAY = [
  ["servis yanit vermiyor", ["surec"]], ["kuyruk birikti", ["surec", "arama"]],
  ["sertifika dogrulanmiyor", ["dosya"]], ["ad cozumlenmiyor", ["ag"]],
  ["disk doldu", ["dosya"]], ["yapilandirma yanlis okundu", ["kabuk", "arama"]],
  ["yavas yanit", ["ag", "surec"]], ["izin reddedildi", ["dosya", "kabuk"]],
];
// Servisin dokuz yerel bagimliligi: [ad, bayt, saglayan en yalin aday sirasi].
// Adaylar zenginden yalina siralidir; sira > saglayan ise bagimlilik temelde yoktur.
const BAGIMLILIK = [
  ["sifreleme kutuphanesi", 3.1e6, 2], ["sertifika deposu", 0.3e6, 2],
  ["matematik kutuphanesi", 1.2e6, 2], ["sikistirma kutuphanesi", 0.6e6, 2],
  ["yerellestirme verisi", 2.4e6, 1], ["saat dilimi veritabani", 0.9e6, 1],
  ["ad cozumleyici eklentisi", 0.9e6, 1], ["surum uyumluluk katmani", 0.6e6, 0],
  ["kabuk betigi calistirici", 0.3e6, 0],
];

console.log("aday".padEnd(15) + "yerinde bakilan".padEnd(17) + "ek adim".padEnd(9) +
  "eksik bagimlilik".padEnd(18) + "eklenen".padEnd(9) + "gercek imaj");
ADAYLAR.forEach((aday, sira) => {
  const arac = ARAC[aday.ad];
  let yerinde = 0, ekAdim = 0;
  for (const [, gerek] of OLAY) {
    if (gerek.every((g) => arac.includes(g))) yerinde += 1;
    else ekAdim += arac.includes("paket") ? 2 : 4;
  }
  const yok = BAGIMLILIK.filter(([, , saglayan]) => sira > saglayan);
  const eklenen = yok.reduce((t, [, b]) => t + b, 0);
  const nominal = envanter(aday).bayt + UYGULAMA;
  console.log(aday.ad.padEnd(15) + `${yerinde}/8 olay`.padEnd(17) +
    String(ekAdim).padEnd(9) + `${yok.length}/9`.padEnd(18) +
    mb(eklenen).padEnd(9) + mb(nominal + eklenen));
});
aday           yerinde bakilan  ek adim  eksik bagimlilik  eklenen  gercek imaj
tam donanimli  8/8 olay         0        0/9               0.0 MB   135.1 MB
kucultulmus    6/8 olay         4        2/9               0.9 MB   35.4 MB
tek ikili      0/8 olay         32       5/9               5.1 MB   33.2 MB

Tek ikili temelde sekiz olayın hiçbirine yerinde bakılamaz ve sekiz olay toplam 32 ek adım üretir. Bu adımlar yalnız süre değildir. Yardımcı bir konteyneri aynı ad alanına bağlamak, imajdan çıkarılan bütün araçları o an geri getirmek demektir; yani yalıtım hata ayıklama süresince bilerek delinir. Küçük temelin kapattığı 480 çalıştırılabilir dosya, olay anında başka bir yoldan geri açılır — fark, artık kalıcı değil süreli olmasıdır ve o sürenin ne zaman başladığı kayda geçebilir.

Son iki sütun boyut tablosunu düzeltir. Tek ikili temel nominal olarak küçültülmüş temelden 6,4 MB küçüktür; ama dokuz bağımlılığın beşi temelde bulunmadığı için imaja elle eklenir ve fark 2,2 MB’ye iner. Eksik bağımlılıklardan biri kabuk betiği çalıştırıcısıdır: kabuk olmayan bir temelde başlangıç betiği çalışmaz, servisin doğrudan çalıştırılabilir olması gerekir. Bu, bayt olarak küçük ama yazım olarak gerçek bir bedeldir.

Küçültülmüş temel iki tarafta da orta değeri tutar: 6/8 olay yerinde, 4 ek adım, 2 eksik bağımlılık. Ölçülen üç nicelik birlikte bakıldığında seçim “en küçüğü” değil, ek adımların kimin üstüne düştüğü sorusudur.

Özet

  • Aynı uygulama üç temel üzerinde 135,1 MB, 34,5 MB ve 28,1 MB çıktı verir; tam donanımlı temelde imajın yüzde 82’si yazılmamış bölümdür ve temel tek başına 3190 dosya taşır.
  • İmajın içindeki çalıştırılabilir dosya sayısı 480 / 140 / 0’dır. Bu sayı saldırı yüzeyine eşit değildir ama üst sınırıdır: bir kod çalıştırma açığında hazır bekleyen araç sayısıdır.
  • Temel güncellemesi belirlenimci derlemede dört katmanın birini, damgalı derlemede dördünü değiştirir. Yıllık çekme tam donanımlı temelde 177,4 GB, tek ikili temelde 0,2 GB’dir; farkın kaynağı bayt kadar sıklıktır (133 güncellemeye karşı 5).
  • Küçük temelin gizli bedeli sayıyla ölçülür: tek ikili temelde 8 olayın 0’ına yerinde bakılabilir, 32 ek adım gerekir ve bu adımlar yalıtımı hata ayıklama süresince bilerek deler.
  • Nominal 6,4 MB’lik boyut farkı, eksik 5 bağımlılık imaja eklendiğinde 2,2 MB’ye iner; temelin taşımadığı her şey imaja geri girer, yalnız başka bir yerden ve elle.

Sonraki Adım

Bu dersin ölçümü üç adayı sabit içerikmiş gibi ele aldı. Oysa hiçbir temel içerikle seçilmez: bir adla çekilir ve o adın hangi içeriği getirdiği zamana bağlıdır. Aynı şey üretilen imajın kendisi için de geçerlidir — 133 güncellemenin her biri yeni bir içerik üretir, ama dağıtım kayıtlarında duran şey addır.

M22/K01’in yapı çıktısı depolarında taşınabilir etiket ile değişmez sürüm ayrımı ölçülmüştü; o sayım tekrarlanmaz. Buradaki soru bir katman daha aşağıdadır: imaj tek bir nesne değil, bir katman listesidir. Sonraki ders bunu sayar — aynı içerik özetine kaç ad işaret ediyor, bir etiket taşındığında dört katmanın gerçekten kaçı değişiyor ve üretime çıkan bir dağıtımın kaynağı özetten geriye izlenebiliyor mu?

İ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