İçeriğe geç
academia.sh

Ders 20 / 22

Zaman Çizelgesi Oluşturma

Üç kaynağın olaylarının tek çizelgede birleştirilmesi ve saat kaymasının sıralamayı bozması: 54 olayın oluşturduğu 1.431 çiftte ham birleştirme 35 ters çift üretiyor, 54 olayın 33'ü yanlış konuma giriyor ve en büyük kayma 243 saniye. On dokuz çapa olayıyla kayma kestirilip düzeltildiğinde ters çift 1'e, yanlış konum 2'ye iniyor ve düzeltme 34 olayın yerini değiştiriyor. Ters çiftlerin 35'inin 35'i iki ayrı kaynaktan gelir; kayma bir kaynağın kendi içindeki sırayı hiç bozmaz.

İçindekiler

Bir önceki ders kalemlerin ne zaman toplandığını ölçtü. Toplanan her kalem kendi zaman damgalarını taşır: dosya değişim anları, oturum açma anları, akış kaydındaki bağlantı anları. İncelemenin bir sonraki adımı bu damgaları tek bir çizgi üzerinde birleştirmektir; çıkan şeye zaman çizelgesi denir ve raporun omurgasıdır.

Çizelgenin taşıdığı iddia sıradır. “Önce yapılandırma değişti, sonra dış bağlantı kuruldu” cümlesi bir zaman bilgisi değil, bir neden sonuç önermesidir; sırası ters çevrilirse tersini söyler. Sıranın dayandığı sessiz varsayım ise bütün kaynakların aynı saati okuduğudur. Bu ders o varsayımı sınar: üç kaynağın olayları birleştirilir, kaç olayın yanlış sıraya girdiği sayılır, kayma kestirilip düzeltilir ve düzeltmenin kaç olayı yerinden oynattığı ölçülür. Olaylar ve saatler kurgudur.

  • AI19. Zaman çizelgesi, farklı kaynaklardaki olayların tek bir eksende sıralanmasıdır. Çizelgenin taşıdığı bilgi zaman değerleri değil, sıradır.
  • AI20. Her kaynağın saati kendi kaymasını taşır: sabit bir sapma ve saniye başına biriken bir sürüklenme. İkisi de kurgudur.
  • AI21. Çapa olayı, iki kaynakta birden kaydedilmiş aynı olaydır. Kayma kestirimi yalnız çapa olaylarından çıkarılır.
  • AI22. Merkez günlüğü başvuru saatidir. Sıralama göreli bir sorudur; mutlak doğruluk gerekmez, kaynakların birbirine göre hizalanması yeter.
  • AI23. Ters çift, gerçekte biri önce olduğu halde çizelgede öteki önce görünen olay çiftidir. Sıralama hatasının ölçüsü budur.
  • AI24. Gerçek zamanlar bu modelde bilinir. Gerçek bir incelemede bilinmez; oradaki tek dayanak çapa olaylarıdır.

Üç Saat, Tek Çizelge

// adli/zaman.mjs — uc kaynagin kurgu olay kayitlari ve saat kaymasi MODELIDIR.
// Gercek kurum, adres ve olay adi yazilmaz; saatler kurgudur.

export const TOHUM = 20260805, N = 54, PENCERE = 7200;   // iki saatlik pencere
const uretec = (t) => { let s = t >>> 0;
  return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; };

// kaynak -> [sabit sapma(sn), suruklenme(sn/sn)]  merkez gunlugu basvuru saatidir
export const KAYNAK = {
  "merkez-gunluk": [0, 0], "uc-nokta-kaydi": [-214, -0.0042], "akis-toplayici": [96, 0.0013],
};
export const TUR = ["oturum-acma", "yapilandirma-degisikligi", "dis-baglanti",
  "surec-baslatma", "dosya-yazma", "yetki-yukseltme"];

// Bildirilen zaman: kaynagin kendi saatinde okunan deger.
export const bildir = (k, t) =>
  Math.round(t + KAYNAK[k][0] + KAYNAK[k][1] * t);

// Olaylar gercek zamanlariyla uretilir; capa olaylari iki kaynakta birden kaydedilir.
export function olaylar() {
  const r = uretec(TOHUM), ad = Object.keys(KAYNAK), liste = [];
  for (let i = 0; i < N; i += 1) {
    const t = Math.floor(r() * PENCERE), k = ad[Math.floor(r() * 3)];
    liste.push({ no: i, t, kaynak: k, tur: TUR[Math.floor(r() * TUR.length)],
      capa: k !== "merkez-gunluk" && r() < 0.3 });
  }
  liste.sort((a, b) => a.t - b.t || a.no - b.no);
  const kayit = [];
  for (const o of liste) {
    kayit.push({ ...o, bildirilen: bildir(o.kaynak, o.t) });
    if (o.capa) kayit.push({ ...o, kaynak: "merkez-gunluk", ikincil: true,
      bildirilen: bildir("merkez-gunluk", o.t) });
  }
  return kayit;
}

// Ters cift: gercekte a once oldugu halde cizelgede b once gorunen olay ciftleri.
export function tersCift(dizi) {
  let n = 0;
  for (let i = 0; i < dizi.length; i += 1)
    for (let j = i + 1; j < dizi.length; j += 1)
      if (dizi[i].t > dizi[j].t) n += 1;
  return n;
}
export const siraya = (kayit, zaman) =>
  [...kayit].sort((a, b) => zaman(a) - zaman(b) || a.no - b.no);

Kayma iki bileşenden oluşuyor ve ikisi ayrı davranır. Sabit sapma kaynağın saatinin baştan beri kaç saniye ileri ya da geri olduğudur; bütün kayıtları aynı miktarda kaydırır. Sürüklenme ise saatin biriken hatasıdır; kaydırma miktarı zamanla büyür. Sabit sapma tek bir sayıyla düzeltilir, sürüklenme düzeltilemez — ancak ölçülüp artık hata olarak yazılabilir.

Ham Çizelge ve Çapa ile Düzeltme

// adli/cizelge.mjs — ham birlestirme, capa ile duzeltme ve kalan ters cift.
import { KAYNAK, N, olaylar, tersCift, siraya } from "./zaman.mjs";

const y = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join("").trimEnd());
const K = olaylar();
const birincil = K.filter((k) => !k.ikincil);
const capa = K.filter((k) => k.capa);

const A = [-18, 8, 8, 15, 16];
y(A, "kaynak", "kayit", "capa", "gercek sapma", "capa kestirimi");
const kestirim = {};
for (const k of Object.keys(KAYNAK)) {
  const c = capa.filter((x) => x.kaynak === k && !x.ikincil);
  const es = c.map((x) => x.bildirilen -
    capa.find((z) => z.no === x.no && z.ikincil).bildirilen);
  kestirim[k] = es.length ? Math.round(es.reduce((a, b) => a + b, 0) / es.length) : 0;
  y(A, k, birincil.filter((x) => x.kaynak === k).length, c.length, KAYNAK[k][0], kestirim[k]);
}

const ham = siraya(birincil, (o) => o.bildirilen);
const duz = siraya(birincil, (o) => o.bildirilen - kestirim[o.kaynak]);
const dogru = siraya(birincil, (o) => o.t);
const yer = (a, b) => a.filter((o, i) => b[i].no !== o.no).length;

console.log("");
const B = [-24, 11, 14, 16];
y(B, "cizelge", "ters cift", "yanlis konum", "en buyuk kayma");
const ciftler = (N * (N - 1)) / 2;
for (const [ad, d, z] of [["ham birlestirme", ham, (o) => o.bildirilen],
  ["capa ile duzeltilmis", duz, (o) => o.bildirilen - kestirim[o.kaynak]],
  ["gercek zaman", dogru, (o) => o.t]])
  y(B, ad, tersCift(d), yer(d, dogru), Math.max(...d.map((o) => Math.abs(z(o) - o.t))));
console.log(`${N} olay, ${ciftler} cift, ${capa.length / 2} capa olayi`);
console.log(`ham cizelgede ters cift orani %${(tersCift(ham) * 100 / ciftler).toFixed(1)}, ` +
  `duzeltmeden sonra %${(tersCift(duz) * 100 / ciftler).toFixed(1)}`);
console.log(`duzeltme ${yer(ham, duz)} olayin cizelgedeki yerini degistiriyor`);
kaynak               kayit    capa   gercek sapma  capa kestirimi
merkez-gunluk           13       0              0               0
uc-nokta-kaydi          25      12           -214            -230
akis-toplayici          16       7             96             100

cizelge                   ters cift  yanlis konum  en buyuk kayma
ham birlestirme                  35            33             243
capa ile duzeltilmis              1             2              15
gercek zaman                      0             0               0
54 olay, 1431 cift, 19 capa olayi
ham cizelgede ters cift orani %2.4, duzeltmeden sonra %0.1
duzeltme 34 olayin cizelgedeki yerini degistiriyor

İki sayı arasındaki fark bu dersin ilk sonucudur. Ham çizelgede ters çift oranı yüzde 2,4‘tür ve küçük görünür; aynı çizelgede 54 olayın **33’ü** yanlış konumdadır, yani olayların yüzde 61’i. Bu iki oran çelişmiyor: birkaç yüz saniyelik bir kayma, olayların çoğunu birkaç sıra kaydırır ama yalnız zaman aralığı kaymadan küçük olan çiftleri tersine çevirir. Çizelgeye “olaylar aşağı yukarı doğru sırada” diye bakan bir okuma yüzde 97,6’lık orana dayanır; raporda kullanılan cümleler ise tam olarak birbirine yakın olaylar hakkında kurulur.

Çapa ile düzeltme ters çifti 35’ten 1’e, yanlış konumu 33’ten 2’ye indiriyor. Kalan bir ters çift bir artıktır ve nedeni tabloda görünüyor: uç nokta kaydının gerçek sapması −214 iken çapa kestirimi −230’dur. On altı saniyelik yanlılık sürüklenmeden gelir. Sabit bir sayıyla yapılan düzeltme, pencerenin ortasında doğru, iki ucunda yanlıştır; en büyük kalan kayma 15 saniyedir. Bu sayı raporda çözünürlük olarak yazılmalıdır: on beş saniyeden yakın iki olayın sırası bu çizelgeyle kanıtlanamaz.

Son satır düzeltmenin ölçeğini veriyor: 34 olayın çizelgedeki yeri değişiyor. Düzeltmeden önce yazılmış bir anlatı, düzeltmeden sonra otuz dört noktada farklı bir metin olurdu.

Çapa Sayısı ve Düzeltmenin Biçimi

// adli/capa.mjs — capa sayisinin ve duzeltme bicimlerinin kalan hataya etkisi.
import { KAYNAK, olaylar, tersCift, siraya } from "./zaman.mjs";

const y = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join("").trimEnd());
const K = olaylar(), birincil = K.filter((o) => !o.ikincil);
// Capa cifti: (basvuru saatinde okunan zaman, iki kayit arasindaki fark).
const cift = (k) => K.filter((o) => o.capa && o.kaynak === k && !o.ikincil).map((o) => {
  const m = K.find((z) => z.no === o.no && z.ikincil);
  return [m.bildirilen, o.bildirilen - m.bildirilen];
});

const sabit = (c) => [Math.round(c.reduce((a, [, d]) => a + d, 0) / c.length), 0];
// Dogrusal uydurma: fark = sapma + suruklenme * zaman.
function dogrusal(c) {
  const n = c.length, st = c.reduce((a, [t]) => a + t, 0), sd = c.reduce((a, [, d]) => a + d, 0);
  const stt = c.reduce((a, [t]) => a + t * t, 0), std = c.reduce((a, [t, d]) => a + t * d, 0);
  const b = (n * std - st * sd) / (n * stt - st * st);
  return [(sd - b * st) / n, b];
}
const geri = ([a, b]) => (o) => (o.bildirilen - a) / (1 + b);

const A = [-7, 15, 12, 14, 14, 13];
y(A, "capa", "sabit kestirim", "sabit ters", "sabit kayma", "dogrusal ters", "dogr. kayma");
for (const n of [2, 4, 8, 12]) {
  const p = {}, q = {};
  for (const k of Object.keys(KAYNAK)) {
    const c = cift(k).slice(0, n);
    p[k] = c.length ? sabit(c) : [0, 0];
    q[k] = c.length > 1 ? dogrusal(c) : [0, 0];
  }
  const d1 = siraya(birincil, (o) => geri(p[o.kaynak])(o));
  const d2 = siraya(birincil, (o) => geri(q[o.kaynak])(o));
  const kayma = (m) => Math.round(Math.max(...birincil.map((o) =>
    Math.abs(geri(m[o.kaynak])(o) - o.t))));
  y(A, n, p["uc-nokta-kaydi"][0], tersCift(d1), kayma(p),
    tersCift(d2), kayma(q));
}
console.log(`\ngercek sapma ${KAYNAK["uc-nokta-kaydi"][0]} sn, gercek suruklenme ` +
  `${KAYNAK["uc-nokta-kaydi"][1]} sn/sn; uc nokta kaydinda ${cift("uc-nokta-kaydi").length} ` +
  `capa var, akis toplayicisinda ${cift("akis-toplayici").length}`);
capa    sabit kestirim  sabit ters   sabit kayma dogrusal ters  dogr. kayma
2                 -218           0            25             0            4
4                 -221           0            22             0            1
8                 -226           1            17             0            1
12                -230           1            15             0            1

gercek sapma -214 sn, gercek suruklenme -0.0042 sn/sn; uc nokta kaydinda 12 capa var, akis toplayicisinda 7

İkinci sütun beklenenin tersine gidiyor. Çapa sayısı ikiden on ikiye çıkarken sabit kestirim −218’den −230’a kayıyor, yani gerçek sapma olan −214’ten uzaklaşıyor. Bu bir hesap hatası değildir: sabit kestirim bütün pencerenin ortalamasıdır ve sürüklenme pencere boyunca birikir. Daha çok çapa, yanlış bir modelin kestirimini doğru yapmaz; onu yalnız daha kararlı biçimde yanlış yapar. Kalan kayma da bunu gösteriyor — 25 saniyeden 15 saniyeye iniyor ve orada duruyor.

İki katsayılı düzeltme aynı çapa kümesiyle farklı bir sonuç veriyor. Fark, zamanın doğrusal bir işlevi olarak uydurulduğunda iki çapayla bile kalan kayma 4 saniyeye, dört çapadan sonra 1 saniyeye iniyor. Aradaki fark veri miktarı değil, modelin biçimidir: sürüklenmesi olan bir saati sabit bir sayıyla düzeltmek, eğimli bir doğruyu yatay bir çizgiyle temsil etmektir.

Ters çift sütunları bu ölçekte karar taşımıyor ve bunu yazmak gerekir. Otuz beşten sıfır ile bir arasına inmiş bir sayıda 0 ile 1 farkı tek bir çiftin hangi tarafa düştüğüdür; asıl bilgi kalan kayma sütunundadır. Bir çizelge “ters çift kalmadı” diye değil, “on beş saniyeden yakın olayların sırası kanıtlanamaz” diye raporlanır.

Doğrusal düzeltmenin bir koşulu vardır ve tablonun okumadığı yerde durur: çapa olaylarının pencereye yayılmış olması. Hepsi pencerenin bir ucunda toplanırsa eğim kestirimi kararsız olur ve düzeltme öteki uçta sabit düzeltmeden daha kötü davranır. Belirleyici olan çapa sayısı değil, çapaların dağılımıdır.

Tersine Dönen Çiftler

// adli/cift.mjs — ham cizelgede tersine donen ciftler ve dogurdugu yanlis cikarim.
import { olaylar, siraya } from "./zaman.mjs";

const y = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join("").trimEnd());
const birincil = olaylar().filter((k) => !k.ikincil);
const ham = siraya(birincil, (o) => o.bildirilen);

const ters = [];
for (let i = 0; i < ham.length; i += 1)
  for (let j = i + 1; j < ham.length; j += 1)
    if (ham[i].t > ham[j].t) ters.push([ham[i], ham[j], ham[i].t - ham[j].t]);
ters.sort((a, b) => b[2] - a[2]);

const KOD = { "merkez-gunluk": "M", "uc-nokta-kaydi": "U", "akis-toplayici": "A" };
const A = [-28, -28, 11, 13];
y(A, "cizelgede once gorunen", "cizelgede sonra gorunen", "ham fark", "gercek fark");
for (const [a, b] of ters.slice(0, 5))
  y(A, `${KOD[a.kaynak]}/${a.tur}`, `${KOD[b.kaynak]}/${b.tur}`,
    `${b.bildirilen - a.bildirilen} sn`, `${b.t - a.t} sn`);

const farkli = ters.filter(([a, b]) => a.kaynak !== b.kaynak).length;
console.log(`\n${ters.length} ters ciftin ${farkli}'i iki ayri kaynaktan geliyor, ` +
  `${ters.length - farkli}'i ayni kaynaktan`);
console.log(`en buyuk tersine donme ${ters[0][2]} saniyelik gercek farki gizliyor`);
cizelgede once gorunen      cizelgede sonra gorunen        ham fark  gercek fark
U/dis-baglanti              A/dis-baglanti                    18 sn      -306 sn
U/dis-baglanti              M/yapilandirma-degisikligi         9 sn      -224 sn
U/yapilandirma-degisikligi  A/surec-baslatma                 141 sn      -200 sn
U/surec-baslatma            A/yapilandirma-degisikligi       145 sn      -191 sn
U/dis-baglanti              A/oturum-acma                    156 sn      -179 sn

35 ters ciftin 35'i iki ayri kaynaktan geliyor, 0'i ayni kaynaktan
en buyuk tersine donme 306 saniyelik gercek farki gizliyor

Son satırdan bir önceki cümle bu dersin en kullanışlı kuralını veriyor: 35 ters çiftin 35’i iki ayrı kaynaktan gelir, hiçbiri aynı kaynağın içinde değildir. Bunun nedeni yapısaldır. Bir kaynağın bütün kayıtları aynı saatten okunur; o saat ne kadar yanlış olursa olsun kendi kayıtlarını aynı miktarda kaydırır ve iç sıralarını korur. Sıra bozulması yalnız kaynaklar arasında doğar.

Bu, incelemeye doğrudan uygulanabilir bir ayrım verir. Tek bir kaynağın içindeki sıra kaymadan bağımsızdır ve ek bir dayanak istemez. İki kaynaktan gelen iki olay arasındaki sıra ise bir iddiadır ve dayanağı ancak kayma ölçüldükten sonra kurulur. Raporda bu ikisi aynı cümle kalıbıyla yazılırsa, ikincisinin taşıdığı belirsizlik görünmez olur.

Tablonun ilk satırı bunun somut karşılığıdır. Uç noktadaki dış bağlantı kaydı ham çizelgede akış toplayıcısındaki dış bağlantı kaydından 18 saniye önce görünüyor; gerçekte 306 saniye sonradır. Bu iki satırı yan yana okuyan bir inceleme, uçtaki bağlantının akış kaydını doğurduğunu düşünür — oysa sıralama tam tersidir ve iki kayıt beş dakikadan uzun bir aralıkla ayrılmıştır. Kaymanın ürettiği hata bir gecikme değil, bir yön hatasıdır.

Özet

  • Zaman çizelgesinin taşıdığı bilgi zaman değerleri değil sıradır; sıra bir neden sonuç önermesi kurar ve ters çevrilirse tersini söyler.
  • Ham birleştirmede 1.431 çiftin 35’i ters çıkar (yüzde 2,4), ama 54 olayın 33’ü yanlış konumdadır; düşük çift oranı çizelgenin doğru olduğu anlamına gelmez.
  • On dokuz çapa olayıyla kestirilen düzeltme ters çifti 1’e, yanlış konumu 2’ye indirir ve 34 olayın çizelgedeki yerini değiştirir.
  • Sabit sapma kestirimi sürüklenmeyi düzeltemez: gerçek sapma −214 iken kestirim −230’dur ve kalan en büyük kayma 15 saniyedir; bu sayı çizelgenin çözünürlüğüdür.
  • Çapa sayısını artırmak sabit kestirimi gerçek sapmaya yaklaştırmaz (−218’den −230’a gider); zamanın doğrusal bir işlevi olarak uydurulan düzeltme iki çapayla kalan kaymayı 4 saniyeye indirir. Belirleyici olan çapa sayısı değil, modelin biçimi ve çapaların pencereye yayılımıdır.
  • Ters çiftlerin tamamı iki ayrı kaynaktan gelir; bir kaynağın kendi içindeki sıra kaymadan etkilenmez, kaynaklar arası sıra ise ölçülmeden iddia edilemez.

Sonraki Adım

Bu derste olaylar hazır kayıt olarak geldi: her birinin bir türü, bir kaynağı ve bir zamanı vardı. Gerçek bir incelemede kayıtların bir bölümü böyle hazır değildir; sistemin kendi işleyişi için tuttuğu yapılardan çıkarılır. Bir yapılandırma deposundaki girdi, bir dosya sistemi meta veri kaydı, bir kısayol, bir önbellek girdisi — bunların hiçbiri “olay günlüğü” olmak üzere yazılmamıştır ama sıralanabilir bir iz bırakır.

Sonraki ders bu yapıları kanıt değeri cinsinden ele alır. Her yapı bir soruya yanıt verir, ama hangi soruya yanıt verdiği yapıdan yapıya değişir: bazısı bir şeyin olduğunu doğrudan gösterir, bazısı ancak bir çıkarım taşır, bazısı ise makinenin olağan kullanımında da oluşur. Bu sonuncusu sayılmadan yazılan her cümle, taban gürültüsünü bulgu diye rapora sokar.

İ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