İçindekiler

Kısaca: MKA Engine bir oyun gününü her seferinde aynı sırayla çalıştırır: komutlar, zamanlayıcılar, sistemler, gün sonu işleri, dünyanın parmak izi ve takvimin ilerlemesi. Sistemler hangi tabloları okuyup yazdığını önceden bildirir; motor bunlardan aşamalar çıkarır ve her aşamanın işini iş parçacıklarına bölüştürür. Sonuç, kaç iş parçacığı kullanılırsa kullanılsın aynı çıkar.
Oyunun saati ilerlediğinde ekranda bir gün geçer. Arkada ise yüz binlerce satır hesaplanır: nüfus büyür, hazineler değişir, zamanlayıcılar çalar, komutlar uygulanır. Bunların hangi sırayla, hangi kuralla ve kaç çekirdekte yapılacağı motorun işidir. Bu günlük bir oyun gününün yolculuğunu anlatıyor. Önceki günlüklerde takvimi ve dünyanın bellekteki halini gördük; şimdi üzerlerinde dönen çarka bakıyoruz.
Bir fabrika vardiyası gibi
Görseldeki fabrikayı düşünün. Vardiya sabah talimatlarla başlar, sonra alarmı kurulmuş işler yapılır, sonra atölyeler çalışır, en sonda defter kapatılır. Ayrı tezgâhlardaki ustalar aynı anda çalışabilir; ama iki usta aynı tezgâha uzanamaz, biri beklemek zorundadır. Motorun bir oyun günü tam olarak böyle işler. Zor kısım, hangi işin hangi tezgâhta olduğunu bilmek ve sonucun hangi sırayla çalışılırsa çalışılsın aynı çıkmasını sağlamak.
Bir günün yedi durağı
Her gün aynı sırayla ilerler. Bu sırayı kendimiz baştan yazdık, çünkü çok oyunculu oyunda herkesin bilgisayarı aynı sırayı izlemek zorunda (Günlük #2).
| Sıra | Durak | Ne olur |
|---|---|---|
| 1 | Komutlar | Oyuncuların o gün için verdiği komutlar, oyuncu ve sıra numarasına göre uygulanır |
| 2 | Zamanlayıcılar | Vadesi gelen zamanlayıcılar, vade ve sıra numarasına göre çalar; yeni zamanlayıcı en erken ertesi güne kurulabilir |
| 3 | Sistemler | Oyunun kuralları aşama aşama koşar; her aşamanın sonunda bırakılan mesajlar uygulanır |
| 4 | Gün sonu | Önce silme, sonra ekleme istekleri uygulanır; arşiv ve silme kuralları işler; dizinler güncellenir |
| 5 | Süresi dolanlar | Süresi biten betik değişkenleri silinir |
| 6 | Parmak izi | Dünyanın özeti yenilenir ve günün parmak izi alınır |
| 7 | İlerleme | Adım sayacı ve tarih bir ileri gider |
Olaylar ve kancalar bu sıraya kendi tanımlı anlarıyla girer; temel iskelet yukarıdaki yedi duraktır. Sıranın küçük ama önemli sonuçları var. Zamanlayıcının işleyicisi yeni bir zamanlayıcıyı en erken ertesi güne kurabildiği için bir işleyici, aynı günün sistemlerinin göreceği dünyayı bozamaz. Gün sonunda ekleme ve silme işlerinin toplu yapılması da Günlük #3'te anlattığımız gibi bir günün bütün sistemlerinin aynı dünyayı görmesini sağlar.
Sistemler aşamalara nasıl dizilir?
Oyunun her kuralı bir sistemdir: "nüfus büyüsün", "ülke geliri hesaplansın". Her sistem, hangi sütunları okuyup hangilerine yazacağını bildirir. Motor bunlara bakarak bir plan çıkarır, kural çok basit: bir sistem, kendisiyle çakışan en son sistemin bir sonraki aşamasına konur; çakışan yoksa ilk aşamaya. İki sistem çakışıyorsa biri diğerinin yazdığını okuyor ya da ikisi aynı şeye yazıyor demektir.
Aynı aşamadaki sistemler birbirinin verisine dokunmadığı için hangi sırayla çalışırsa çalışsın sonuç aynıdır. Plan oyun yüklenirken bir kez çıkarılır; gün içinde hiçbir şey hesaplanmaz.
Bir sistem başka bir satıra bir şey söylemek isterse mesaj bırakır; mesajlar aşamanın sonunda sistem, parça ve yazılış sırasıyla uygulanır. Bu yüzden mesajı yazan sistem, mesajın etkisini aynı aşamada göremez; okuyanlar bir sonraki aşamayı bekler.
İş parçacıkları nasıl çalışır?
Aynı tezgâhta beklemeyen işleri bölüştürmek için motor oyun başlarken sabit sayıda iş parçacığı açar ve oyun boyunca kapatmaz. Bir aşamanın işi numaralı parçalara bölünür; her iş parçacığı sıradaki numarayı alır, işler, bir sonrakini alır. Çağıran iş parçacığı da çalışır; yani 8 iş parçacığı, 8 işçi demektir. Böylece her gün iş parçacığı açıp kapatma maliyeti ödenmez ve yavaş biten bir parça yüzünden kimse boş beklemez.
Hangi iş parçacığı hangi parçayı alırsa alsın sonuç değişmez: parçaların sonuçları parça sırasıyla birleşir. Bu yüzden 1 iş parçacığıyla da 16 iş parçacığıyla da aynı oyun oynanır.
Ölçtük
Ekransız koşucuyla, 30.000 konumlu, 250 ülkeli ve 2 milyon nüfus birimli basit bir dünyada 12 oyun yılı (4.380 gün) koşturduk. Dünyada dört sistem var; birbirleriyle çakıştıkları için dört ayrı aşamaya düştüler. Yani burada hız, sistemleri yan yana koşturmaktan değil, her sistemin satırlarını iş parçacıkları arasında bölmekten geliyor.
12. yılın bir oyun günü, iş parçacığı sayısına göre (ms)
| Etiket | Süre |
|---|---|
| 1 | 4,58 |
| 2 | 2,79 |
| 4 | 1,40 |
| 8 | 0,90 |
| 16 | 0,94 |
Bir iş parçacığından sekize çıkınca gün yaklaşık 5 kat hızlandı (4,58 ms'den 0,90 ms'ye). Ondan sonrası yatay: 16 iş parçacığı sekizden daha hızlı değil. Sebebi basit: işin bir kısmı bölünemiyor. Sekiz iş parçacığında günün bir bölümü küçük aşamalara ve parmak izine gidiyor; bunlar kısa olduğu için bölmenin kazancı yok. Bu, paralel çalışmanın bilinen sınırı (Amdahl yasası (yeni sekmede açılır)): işin bölünemeyen kısmı, kaç işçi eklenirse eklensin süreyi bir tabanın altına indirmez.
Beş iş parçacığı sayısında da (1, 2, 4, 8, 16) 12 yılın sonundaki parmak izi aynı çıktı: oyun aynı oynandı.
| Parça | Süre (ms) |
|---|---|
| 1. aşama: nüfus güncellemesi | 0,60 |
| 2. aşama: konum nüfusu | 0,08 |
| 3. aşama: konum günlüğü | 0,21 |
| 4. aşama: ülke günlüğü | 0,06 |
| Parmak izi | 0,12 |
İlk aşamada sistemin işi iş parçacıklarına toplam yaklaşık 3,95 ms olarak yayıldı ama duvar saatine 0,60 ms olarak yansıdı: işi yaklaşık 6,6 kat bölmüş olduk (hesap, ölçüm değil). Küçük aşamalar ise zaten bölünecek kadar büyük değil.
Her şey her gün çalışmaz
Bir oyunun her kuralı her gün çalışmaz: vergi ayda bir toplanır, nüfus sayımı ayda bir yapılır, bazı olaylar yılda bir kontrol edilir. Her sistem sıklığını bildirir: her adım, günlük, haftalık, aylık ya da yıllık.
Aylık bir iş ay başında tek günde yapılırsa, ay başındaki gün diğerlerinden çok uzun sürer ve oyun her ay bir an takılır. Biz aylık işi 30 güne yayıyoruz: satırlar 30 eşit dilime bölünür ve her gün bir dilim işlenir. Ay bittiğinde her satır tam bir kez işlenmiş olur ve hiçbir gün işin tamamını taşımaz.
- 2 30 güne yayılan sistem (nüfus güncellemesi, aylık sayım)
- 1,001 ay başı günlerinin diğer günlere süre oranı (8 iş parçacığı, 144 ay başı)
- 1,153 30 günlük döngüde en yavaş günün en hızlıya oranı
Ay başı günleri, ayın diğer günlerinden ölçülebilir ölçüde yavaş değil. Yani aylık sistemler günler arasında bir sıçrama yaratmıyor.
Günde birden fazla tur
Motor takvim gününü temel birim tutar ama oyun yüklenirken adımın uzunluğunu seçebilir: günde N tur, günlük, haftalık ya da aylık. Savaş gibi ince adımlı sistemler olan oyunlar günde birkaç tur isteyebilir. Bu seçeneği baştan açtık, çünkü sonradan eklemek zamanlayıcıya ve kayıt biçimine yeniden dokunmak demekti. Rastgele sayılar ve kayıtlar gün yerine adım numarasıyla tutulur; bu yüzden tur sayısı değişse de belirlenimcilik bozulmaz.
Sınırlar
- Paralellik sistemlerin çakışmasına bağlı: Çok sistem aynı tabloya yazıyorsa aşama sayısı artar ve aşamalar arasında beklenir. Satırları bölmek bunu bir ölçüde telafi eder ama her işi bölmek mümkün değil.
- Bölünemeyen kısım: Küçük aşamalar ve parmak izi, çok iş parçacığında hızı sınırlıyor. Ölçümümüzde 8 iş parçacığından sonrası kazanç getirmedi.
- Ölçümün kapsamı: Dört sistemli basit bir dünya. Gerçek bir oyunun yüzlerce sistemi aşama sayısını ve dağılımı değiştirecek; bu günlükteki sayılar o oyunun hızını göstermez.
- Ayın en yavaş günü: Yayma, ay başı sıçramasını giderir ama günler arasında yine küçük farklar var (en yavaş gün en hızlıdan yüzde 15 yavaş).
- Yayılan işin gecikmesi: Aylık iş 30 güne yayılınca bir satır, ayın başka bir gününde işlenir. Kural tasarımı bunu bilmeli: "ay başında herkes aynı anda" varsayımı yoktur.
Sık sorulanlar
Oyun motorunda paralel çalışma nasıl güvenli olur?
Her sistem hangi tabloları okuyup yazacağını önceden bildirir; motor çakışan sistemleri ayrı aşamalara koyar, aynı aşamadakiler birbirinin verisine dokunmaz. Bu denetim oyun yüklenirken yapılır, gün içinde hiçbir şey denetlenmez.
İş parçacığı sayısı oyunun sonucunu değiştirir mi?
Hayır. Parçaların sonuçları parça sırasıyla birleştiği ve rastgele sayılar sıradan bağımsız hesaplandığı için 1 iş parçacığıyla da 16 iş parçacığıyla da aynı oyun oynanır. Ölçümümüzde beş iş parçacığı sayısında da aynı parmak izi çıktı.
Sistemler hangi sırayla çalışır?
Sistemler aşamalara ayrılır; aşamalar sırayla çalışır, aynı aşamadaki sistemler birbirinden bağımsızdır. Bir günün genel sırası komutlar, zamanlayıcılar, sistemler, gün sonu işleri, parmak izi ve takvimin ilerlemesidir.
Aylık işler neden 30 güne yayılır?
Ay başında tek günde yapılırsa o gün diğerlerinden çok uzun sürer ve oyun takılır. 30 dilime bölününce her gün işin otuzda biri yapılır. Ölçümümüzde ay başı günleri diğer günlerle aynı hızdaydı.
Kaynaklar ve kayıtlar
Dış kaynaklar:
- Vikipedi, Amdahl's law (paralel hızlanmanın sınırı) (yeni sekmede açılır)
- Vikipedi, Thread pool (uzun ömürlü iş parçacığı havuzu) (yeni sekmede açılır)
İç kayıtlarımız (motorun deposu kapalı olduğu için bağlantı veremiyoruz):
- Adım evre sırası kararı: bir günün yedi durağı ve olay, kanca yerleri.
- Adım uzunluğu kararı: günde N tur, günlük, haftalık, aylık adım; sistem sıklıkları.
- İş parçacığı ölçümü: 16 Ekim 2026, 12 oyun yılı, 1, 2, 4, 8 ve 16 iş parçacığı, her biri 3 koşu, dondurulmuş kod kopyası, bilgisayar yüklüyken.
Bir sonraki günlükte oyunun içeriğini yazdığımız dili anlatacağız: tablolar, kurallar ve sayılar motora nasıl tanıtılır?
Bu günlük hakkında sorularınız ya da önerileriniz varsa bize iletişim sayfasından yazabilirsiniz. Motorun genel tanıtımı için MKA Engine sayfasına, bütün günlükler için Geliştirici Günlükleri listesine bakabilirsiniz.
Kaynaklar ve ilgili belgeler
Bunlar da ilginizi çekebilir
- Bir strateji oyununun dünya haritası nasıl yapılır?
MKA Engine için gerçek veriden 27.357 konumluk bir 1337 dünya haritası ürettik: arazi, nehirler, boğazlar, nüfus ve konum sınırları nasıl çıkarıldı?
- Oyun motoruna giden yol
MKA Engine'e nasıl başladık: dört oyunu okumak, belirlenimciliği yasa saymak, aşama aşama ölçerek ilerlemek ve şu an neredeyiz.