Ders 04 / 13
Kabaca Büyüklük Hesabı
On iki varsayımın tek bir tabloda toplanması ve tablodan istek hızı, veri artışı ile bant genişliği ihtiyacının aritmetikle çıkarılması: tepe yükün hesaplanması, önbelleğin arkasındaki yük dengesinin bulunması, seyrek toplu işin bant genişliğine hâkim olması ve her varsayımın hangi sonucu kaç katına çıkardığının ölçülmesi.
İçindekiler
Önceki iki ders sayısı olmayan iki boşluk bıraktı. Nitelik senaryosunun ortam parçası “tepe yükünde” yazıyordu ve tepe yükün kaç istek olduğu belirsizdi; eşiklerin karşılanabilir olup olmadığı da aynı belirsizliğe bağlıydı. İkinci derste altı yanıtsız soru altı varsayıma dönüşmüştü ama varsayımlar hiçbir yere yazılmamıştı.
Bu ders o boşluğu doldurur. Kabaca büyüklük hesabı (back-of-the-envelope estimate), bir tasarımın kaynak ihtiyacını az sayıda varsayımdan aritmetikle çıkarma işidir. Amacı doğru sayıyı bulmak değil, doğru büyüklük sırasını bulmak ve tasarım kararlarının hangi varsayıma dayandığını görünür kılmaktır.
Varsayım Tablosu
Bütün hesapların tek bir kaynağı olur. Aşağıdaki on üç varsayım kursun geri kalanında da kullanılır; hiçbir ders kendi başına yeni bir hacim sayısı seçmez.
| Kod | Varsayım | Değer | Gerekçe |
|---|---|---|---|
| V1 | günlük etkin kullanıcı | 2.000.000 | takip sayfasını günde en az bir kez açan alıcı ve satıcı |
| V2 | kullanıcı başına günlük takip sorgusu | 6 | bir gönderi teslime kadar birkaç kez sorulur |
| V3 | günde oluşan yeni gönderi | 400.000 | satıcı başına günlük gönderi sayısının toplamı |
| V4 | gönderi başına durum olayı | 7 | kabul, aktarma, dağıtıma çıkış, teslim ve ara durumlar |
| V5 | takip yanıtı gövdesi | 480 bayt | durum, bölge, güncellenme zamanı ve son üç rota adımı |
| V6 | bir durum olayının kaydı | 220 bayt | takip numarası, durum, rota adımı, zaman damgası |
| V7 | bir gönderi kaydı | 900 bayt | ağırlık, hacim, bölge, sözleşme ve tarife alanları |
| V8 | tepe çarpanı | 3 | tepe saatteki hızın gün ortalamasına oranı |
| V9 | takip sorgusunun önbellekten karşılanma oranı | 0,90 | aynı takip numarası kısa aralıkla yeniden sorulur |
| V10 | gün sonu işinin penceresi | 4 saat | satıcı raporu sabah ister |
| V11 | ücretlendirmenin taradığı gün | 30 | ücretlendirme aylık dönem üzerinden mutabık kalınır |
| V12 | kaydın saklanma süresi | 730 gün | sözleşme uyuşmazlıkları iki yıl geriye gidebilir |
| V13 | bir fatura satırında toplanan kalem | 100 | bir satıcının bir günü tek fatura satırıdır; dönem kayıtlarının bölümlenmesi bu orana bağlıdır |
Tablonun her satırı bir varsayımdır: doğruluğu tasarımın içinden gösterilemez. Bant genişliği kavramı Bilgisayar Ağları müfredatında kuruldu ve burada yeniden anlatılmaz; hesapta yalnız gövde baytları sayılır, başlık ve protokol yükü ayrı bir varsayım olurdu.
// tasarim/varsayim.mjs — kursun tek varsayim tablosu; butun hesaplar bu tablodan cikar export const V = { gunlukKullanici: 2_000_000, // V1 kullaniciBasinaSorgu: 6, // V2 gunlukGonderi: 400_000, // V3 gonderiBasinaOlay: 7, // V4 takipYanitiBayt: 480, // V5 olayKaydiBayt: 220, // V6 gonderiKaydiBayt: 900, // V7 tepeCarpani: 3, // V8 onbellekIsabeti: 0.9, // V9 topluPencereSaat: 4, // V10 topluKapsananGun: 30, // V11 saklamaGun: 730, // V12 faturaSatirinaKalem: 100, // V13 }; export const GUN_SANIYE = 86_400; export function hesapla(v) { const gunlukSorgu = v.gunlukKullanici * v.kullaniciBasinaSorgu; const gunlukOlay = v.gunlukGonderi * v.gonderiBasinaOlay; const okumaOrt = gunlukSorgu / GUN_SANIYE; const yazmaOrt = gunlukOlay / GUN_SANIYE; const okumaTepe = okumaOrt * v.tepeCarpani; const yazmaTepe = yazmaOrt * v.tepeCarpani; const depoOkuma = okumaTepe * (1 - v.onbellekIsabeti); const topluBayt = v.topluKapsananGun * v.gunlukGonderi * v.gonderiKaydiBayt; const gunlukBayt = v.gunlukGonderi * v.gonderiKaydiBayt + gunlukOlay * v.olayKaydiBayt; return { "gunluk takip sorgusu": gunlukSorgu, "gunluk durum olayi": gunlukOlay, "ortalama okuma istek/s": okumaOrt, "tepe okuma istek/s": okumaTepe, "tepe yazma istek/s": yazmaTepe, "tepe ucta istek/s": okumaTepe + yazmaTepe, "onbellek arkasi okuma/s": depoOkuma, "depoya ulasan istek/s": depoOkuma + yazmaTepe, "depoda yazma/okuma orani": yazmaTepe / depoOkuma, "okuma cikis Mbit/s": (okumaTepe * v.takipYanitiBayt * 8) / 1e6, "yazma giris Mbit/s": (yazmaTepe * v.olayKaydiBayt * 8) / 1e6, "toplu is okunan GB": topluBayt / 1e9, "toplu is tarama kayit/s": (v.topluKapsananGun * v.gunlukGonderi) / (v.topluPencereSaat * 3600), "toplu is Mbit/s": (topluBayt * 8) / (v.topluPencereSaat * 3600 * 1e6), "gunluk veri artisi MB": gunlukBayt / 1e6, "saklanan veri GB": (gunlukBayt * v.saklamaGun) / 1e9, "gunluk fatura satiri": v.gunlukGonderi / v.faturaSatirinaKalem, "donem satici-gun": (v.topluKapsananGun * v.gunlukGonderi) / v.faturaSatirinaKalem, }; }
Birimler ondalık sayılır: MB bayt, GB bayt, Mbit/s bit/s. Karışıklığı önlemek için hesabın içinde yalnız bayt ve saniye kullanılır, dönüştürme son adımda yapılır.
Hesaplar
// tasarim/olcek.mjs — varsayim tablosundan cikan butun hesaplar import { V, hesapla } from "./varsayim.mjs"; const r = hesapla(V); const bicim = (x) => (Number.isInteger(x) ? String(x) : x.toFixed(2)); for (const [ad, deger] of Object.entries(r)) console.log(`${ad.padEnd(26)}${bicim(deger).padStart(12)}`); const gonderiBasinaMs = 1000 / r["toplu is tarama kayit/s"]; console.log(`\ntoplu iste gonderi basina sure = ${gonderiBasinaMs.toFixed(2)} ms (tek isci varsayimiyla)`); console.log(`ucret cagrisi esigi 1 ms -> kalan pay = ${(gonderiBasinaMs - 1).toFixed(2)} ms`); console.log(`toplu is bant genisligi / tepe okuma cikisi = ${(r["toplu is Mbit/s"] / r["okuma cikis Mbit/s"]).toFixed(2)}`);
gunluk takip sorgusu 12000000 gunluk durum olayi 2800000 ortalama okuma istek/s 138.89 tepe okuma istek/s 416.67 tepe yazma istek/s 97.22 tepe ucta istek/s 513.89 onbellek arkasi okuma/s 41.67 depoya ulasan istek/s 138.89 depoda yazma/okuma orani 2.33 okuma cikis Mbit/s 1.60 yazma giris Mbit/s 0.17 toplu is okunan GB 10.80 toplu is tarama kayit/s 833.33 toplu is Mbit/s 6 gunluk veri artisi MB 976 saklanan veri GB 712.48 gunluk fatura satiri 4000 donem satici-gun 120000 toplu iste gonderi basina sure = 1.20 ms (tek isci varsayimiyla) ucret cagrisi esigi 1 ms -> kalan pay = 0.20 ms toplu is bant genisligi / tepe okuma cikisi = 3.75
Bu yirmi bir sayının hepsi hesap sınıfındadır: varsayım tablosundan aritmetikle çıkmıştır ve hiçbiri dışarıdan alınmamıştır. Beşi tasarımı doğrudan etkiliyor.
Tepe yük sanıldığı yerde değil. Uçta tepe istek hızı saniyede 513,89. Bunun 416,67’si okuma, 97,22’si yazma. Okuma akışı hâkim görünüyor — ama önbelleğin arkasında tablo tersine dönüyor: depoya ulaşan okuma 41,67, yazma 97,22 ve depodaki yazma/okuma oranı 2,33. Okuma ağırlıklı diye tarif edilen sistem, deponun gördüğü yerde yazma ağırlıklıdır. Önbellek burada bir strateji olarak değil, yalnız hesapta bir çarpan olarak geçiyor; önbellekleme Eşzamansız İşleme kursunda kuruldu.
Seyrek akış bant genişliğine hâkim. Tepe okuma çıkışı 1,60 Mbit/s, gün sonu işinin okuma hızı 6 Mbit/s: oran 3,75. Günde bir kez koşan iş, günün her saniyesi koşan okuma akışının üç buçuk katı bant genişliği istiyor, çünkü 10,80 GB’ı dört saatlik bir pencereye sıkıştırıyor. Bir tasarımın en büyük kaynak kalemi en sık çalışan akış olmak zorunda değildir.
Bir eşik hesaptan doğrulanabilir. Önceki dersin ücret çağrısı eşiği 1 milisaniyeydi ve keyfi görünüyordu. Tarama hızı saniyede 833,33 kayıt olduğuna göre gönderi başına 1,20 milisaniye vardır; 1 milisaniyelik eşik 0,20 milisaniye pay bırakıyor. Eşiğin kaynağı böylece bir beklenti değil bir hesap oluyor. Sayı tek işçi varsayımıyla geçerlidir: iş paralel işçilere bölünürse pay büyür, ama bu bir tasarım kararıdır, aritmetiğin sonucu değil.
Bir rastlantı hesabın tekrarlanmasını gerektiriyor. Depoya ulaşan tepe istek hızı 138,89 ve ortalama okuma hızı da 138,89. İki sayı eşit çünkü olmasıdır; bu bir bağıntı değil, seçilen varsayımların ürettiği bir çakışmadır. Varsayımlardan biri değiştiğinde eşitlik bozulur, bu yüzden hesap ezberlenmez, yeniden koşturulur.
Bir bölme iki ayrı sayı verir. Günde 400.000 gönderi V13 oranıyla günde 4000 fatura satırına düşüyor; her satır bir satıcının bir gününe karşılık geldiğine göre bu sayı aynı zamanda satıcı sayısıdır. Otuz günü tarayan ücretlendirme işi ise 120.000 satırla karşılaşır. İki sayı aynı bölmeden çıkıyor ama aynı şeyi saymıyor: 4000 satıcı, 120.000 satıcı-gün. Bu kursun ilerleyen Temel Nitelikler konusu gün sonu işini bu ikinci sayı üzerinden bölümlere ayırır, bu yüzden ikisinin birbirinin yerine kullanılmaması gerekir.
Duyarlılık
Bir varsayım tablosunun en önemli çıktısı sayılar değil, sayıların varsayımlara duyarlılığıdır. Aşağıdaki betik on üç varsayımı tek tek oynatır ve yedi sonucun kaç katına çıktığını yazar. Önbellek isabeti ikiye katlanamayacağı için oynatması isabetsizliğin iki katına çıkması olarak tanımlanmıştır; toplu pencere ile fatura satırına toplanan kalem ise yarılanır, çünkü ikisinin de sıkılaşması küçülmesidir.
// tasarim/duyarlilik.mjs — her varsayim tek basina oynatildiginda hangi sonuc kac katina cikiyor import { V, hesapla } from "./varsayim.mjs"; const OYNAMA = { gunlukKullanici: (v) => v * 2, kullaniciBasinaSorgu: (v) => v * 2, gunlukGonderi: (v) => v * 2, gonderiBasinaOlay: (v) => v * 2, takipYanitiBayt: (v) => v * 2, olayKaydiBayt: (v) => v * 2, gonderiKaydiBayt: (v) => v * 2, tepeCarpani: (v) => v * 2, onbellekIsabeti: () => 0.8, // isabet 0.90 -> 0.80: isabetsizlik iki katina cikiyor topluPencereSaat: (v) => v / 2, // pencere yarilaniyor: ayni is yarim surede bitmeli topluKapsananGun: (v) => v * 2, saklamaGun: (v) => v * 2, faturaSatirinaKalem: (v) => v / 2, // satira yarisi kadar kalem toplanir }; const SONUC = [["tepe ucta istek/s", "uc/s"], ["depoya ulasan istek/s", "depo/s"], ["okuma cikis Mbit/s", "cikis"], ["toplu is Mbit/s", "toplu"], ["gunluk veri artisi MB", "artis"], ["saklanan veri GB", "saklama"], ["donem satici-gun", "sat-gun"]]; const taban = hesapla(V); const kat = {}; console.log(`${"oynatilan varsayim".padEnd(26)}${SONUC.map(([, k]) => k.padStart(8)).join("")}`); for (const [ad, oynat] of Object.entries(OYNAMA)) { const yeni = hesapla({ ...V, [ad]: oynat(V[ad]) }); kat[ad] = SONUC.filter(([s]) => Math.abs(yeni[s] - taban[s]) > 1e-9).map(([s]) => s); const satir = SONUC.map(([s]) => (kat[ad].includes(s) ? `x${(yeni[s] / taban[s]).toFixed(2)}` : "-").padStart(8)); console.log(`${ad.padEnd(26)}${satir.join("")}`); } const enGenis = Object.entries(kat).sort((a, b) => b[1].length - a[1].length)[0]; console.log(`\nen cok sonuc oynatan varsayim = ${enGenis[0]} (${enGenis[1].length}/${SONUC.length})`); for (const [s] of SONUC) { const kaynak = Object.keys(kat).filter((a) => kat[a].includes(s)); console.log(`${s.padEnd(23)} bagli varsayim = ${kaynak.length}`); }
oynatilan varsayim uc/s depo/s cikis toplu artis saklama sat-gun gunlukKullanici x1.81 x1.30 x2.00 - - - - kullaniciBasinaSorgu x1.81 x1.30 x2.00 - - - - gunlukGonderi x1.19 x1.70 - x2.00 x2.00 x2.00 x2.00 gonderiBasinaOlay x1.19 x1.70 - - x1.63 x1.63 - takipYanitiBayt - - x2.00 - - - - olayKaydiBayt - - - - x1.63 x1.63 - gonderiKaydiBayt - - - x2.00 x1.37 x1.37 - tepeCarpani x2.00 x2.00 x2.00 - - - - onbellekIsabeti - x1.30 - - - - - topluPencereSaat - - - x2.00 - - - topluKapsananGun - - - x2.00 - - x2.00 saklamaGun - - - - - x2.00 - faturaSatirinaKalem - - - - - - x2.00 en cok sonuc oynatan varsayim = gunlukGonderi (6/7) tepe ucta istek/s bagli varsayim = 5 depoya ulasan istek/s bagli varsayim = 6 okuma cikis Mbit/s bagli varsayim = 4 toplu is Mbit/s bagli varsayim = 4 gunluk veri artisi MB bagli varsayim = 4 saklanan veri GB bagli varsayim = 5 donem satici-gun bagli varsayim = 3
Matris üç şey söylüyor. Birincisi, hiçbir varsayım bütün sonuçları oynatmıyor: en geniş etkili varsayım günlük gönderi sayısı ve o da yedi sonucun altısını tutuyor. İkincisi, “iki katına çıkarsa iki katına çıkar” beklentisi çoğu hücrede yanlış. Günlük etkin kullanıcı iki katına çıktığında uçtaki tepe istek hızı 1,81 katına çıkıyor, çünkü yazma akışı bu varsayıma bağlı değil; deponun gördüğü yük yalnız 1,30 katına çıkıyor, çünkü okumanın yüzde onu depoya ulaşıyor. Aynı büyüme farklı katmanlarda farklı büyüklükte görünüyor.
Üçüncüsü, bir sonucun kaç varsayıma bağlı olduğu güvenilirliğinin ölçüsüdür. Depoya ulaşan istek hızı altı varsayıma birden bağlı; içlerinden biri yanlışsa sayı yanlıştır. Saklanan veri beş varsayıma bağlı. Bu yüzden bir tasarım tartışmasında “depoya saniyede yüz otuz dokuz istek geliyor” cümlesi tek başına savunulamaz; savunma varsayım tablosuna işaret eder.
Özet
- Kabaca büyüklük hesabı doğru sayıyı değil doğru büyüklük sırasını arar; girdisi tek bir yerde toplanmış varsayım tablosudur.
- On üç varsayımdan çıkan hesaplar: uçta tepe 513,89 istek/s (okuma 416,67, yazma 97,22), günlük veri artışı 976 MB, 730 günde 712,48 GB, günde 4000 fatura satırı ve dönemde 120.000 satıcı-gün — son ikisi aynı bölmeden çıkar ama aynı şeyi saymaz.
- Önbelleğin arkasında yük dengesi tersine dönüyor: depoya ulaşan okuma 41,67, yazma 97,22 ve yazma/okuma oranı 2,33 — okuma ağırlıklı sistem depoda yazma ağırlıklıdır.
- Seyrek akış bant genişliğine hâkim olabilir: gün sonu işi 10,80 GB’ı dört saate sıkıştırdığı için 6 Mbit/s istiyor, tepe okuma çıkışının 3,75 katı.
- Bir eşik hesapla doğrulanabilir: tarama saniyede 833,33 kayıt olduğundan gönderi başına 1,20 ms vardır ve önceki dersin 1 ms eşiği 0,20 ms pay bırakır.
- Duyarlılık matrisi “iki kat girdi iki kat sonuç” beklentisini yanlışlıyor: günlük kullanıcı iki katına çıktığında uçtaki tepe 1,81, depodaki yük 1,30 katına çıkıyor.
Sonraki Adım
Elde bir bileşen listesi, bir eşik kümesi ve yirmi bir hesaplanmış sayı var. Bunlar bir tasarım değil, tasarımın malzemesidir; tasarım bir başkasına anlatılıp savunulduğunda vardır. Sonraki ders bu anlatımı ele alır: bileşenlerin ve akışların diyagrama nasıl geçtiğini, hangi sayının hangi kenarda durduğunu, ödünleşimin nasıl yazıldığını ve her sayının yanına sınıfının yazılmasının anlatımı nasıl denetlenebilir kıldığını.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.