ENABLE_OPTIMIZATION_ITEMPROTO_O1

  • Konuyu açan Konuyu açan M29
  • Açılış Tarihi Açılış Tarihi
  • Yanıt Yanıt 2
  • Gösterim Gösterim 287

M29

MT Üye
MT Üye
Mesaj
383
Çözümler
11
Beğeni
212
Puan
749
Ticaret Puanı
0

ENABLE_OPTIMIZATION_ITEMPROTO_O1


  • Aşağıdaki direktif eklendi:
    • Server/common/CommonDefines.h
      • #define ENABLE_OPTIMIZATION_ITEMPROTO_O1
  • Game Core:
    • Server/game/src/item_manager.h
      • m_map_itemProtoByVnum (TR1_NS::unordered_map<DWORD, TItemTable*>)
      • m_map_itemProtoByRangeCache (TR1_NS::unordered_map<DWORD, TItemTable*>)
    • Server/game/src/item_manager.cpp
      • Initialize() sırasında O(1) map yapısı oluşturuldu,
      • reload sırasında yapılar temizleniyor (m_vec_item_vnum_range_info, m_map_vid, O(1) map’ler),
      • GetTable() ilgili direktif altında O(1) yoluna geçirildi + range/cache fallback korundu.
  • DB Core:
    • Server/db/src/ClientManager.h
      • m_map_itemTableByVnum ilgili direktif altında boost::unordered_map olarak değiştirildi.

Önceden sunucu item verisini daha yavaş bir yöntemle arıyordu.
Şimdi ise vnum üzerinden daha hızlı bir arama sistemi eklendi.


Tam olarak ne yapıldı?


unordered_map tipinde map’ler eklendi. Bu sayede item proto çok daha hızlı bulunabiliyor.


Şunun yerine:


  • ara yapılarda arama yapmak,
  • ya da daha yavaş bir arama çalıştırmak,

sunucu artık şunları yapabiliyor:


  • doğrudan vnum değerini kontrol etmek,
  • ve ilgili TItemTable verisini almak.

Bu neden daha hızlı?


Çünkü önceden lookup yaklaşık olarak şöyleydi:


  • O(log n),
    ya da kullanılan yola göre daha yavaş,

şimdi ise:


  • exact lookup’lar için ortalama O(1).

Yani:


  • item ile ilgili işlem sayısı ne kadar fazlaysa,
  • bu değişikliğin anlamı ve katkısı o kadar büyük olur.

Bu nerelerde önem kazanıyor?


Özellikle hot path’lerde, yani sunucunun itemlerle çok sık çalıştığı yerlerde:


  • char_item.cpp
  • shop_manager.cpp
  • item.cpp
  • cube.cpp
  • mağaza sistemleri,
  • questler,
  • tombala,
  • item oluşturma işlemleri

Range kullanan itemlerde durum ne?


dwVnumRange için eski mantık korunmuştur.


Yani:


  • exact vnum doğrudan map üzerinden bulunur,
  • item range üzerinden çalışıyorsa yine fallback ve cache ile işlenmeye devam eder.

Proto reload durumunda ne oluyor?


Reload sırasında:


  • eski map’ler temizleniyor,
  • cache temizleniyor,
  • her şey baştan yeniden oluşturuluyor.

Bu önemlidir çünkü map’ler m_vec_prototype içindeki verilere işaretçi tutuyor.
Eğer yeniden oluşturulmazlarsa eski veya geçersiz kayıtlar kalabilirdi.


Pointer güvenliği nasıl sağlandı?


Geliştirici bunu şu şekilde ele aldı:


  • exact/range map’ler Initialize() sırasında yeniden oluşturuluyor,
  • eski yardımcı yapılar da temizleniyor,
  • mevcut itemler yine SetProto(GetTable(...)) ile proto almaya devam ediyor.

Yani amaç, reload sonrasında eski pointer’ların kalmamasını sağlamaktır.


Gerçek etkisi nedir?


Tüm core’un sihirli şekilde %50 daha hızlı olmasını beklemeyin.


Daha gerçekçi olarak:


  • tekil proto lookup artık daha ucuz,
  • tüm core birkaç % CPU kazanabilir,
  • en büyük etki, item işlemlerinin yoğun olduğu yerlerde görülür.
 

Dosya Eklentileri

metin2'yi bir kenara bırakıp "bilgisayar bilimleri" dilinde düşünecek olursak;

N = 10.000 olmak üzere;

bir sunucuda ortalama N item olsun, itemtable da 500byte olsa total byte ne eder? yaklaşık 5 megabyte

arkadaşın yaptığını analiz edelim;

N adet itemi bir containera eklemek istiyoruz(niyet cachelemek)

`unordered_map` yani "Hash Table" kullanılmış iyi güzel;

initialize'a bakarsak `unordered_map` reserve edilebilirken edilmemiş yani; N itemi ekleyeceksiniz ve açılışta ortalama derleyiciye göre değişken olarak bilmem kaç kez reallocation yaşayacaksınız (start-up darboğazı), tabii reserve ederseniz çözülecek.

kağıt üzerinde complexity "O(1)" (worst case'de de O(size())) olacaktır tabii yazar haklı, alandan uzak bir kişi bir yerden duyuyor "abi O(1) ya constant time ya anında buluyor ya mükemmel ya!!!", peki.

ee neye laf edeceksin?

`unordered_map` dediğimiz container "node-based" çalışır. 5 MB'lık veri modern bir işlemcinin L3 cache'ine ardışık(contiguous) şekilde sığabilir (Ryzen 5 5600'da L3 cache 32MB) sen bu yapıyla CPU'ya sürekli "pointer chasing" yaptırıp memory fetch için bekletiyorsun, yani cache missler havada uçuşuyor. DOD felsefesiyle baksak, N adet item için flat bir `std::vector` tutup ID'ye göre sıraladıktan sonra "binary_search" atmak ki complexity log2(last - first) + O(1) kağıt üzerinde baksan "çok yaww" dersin, o hash hesaplama ve bucket atlama maliyetinden (ve memory fragmentation'dan) daha performanslıdır. Sanırsam 10k itemden aradığın itemi ortalama 13 döngüde bulabilirsiniz (2 üzeri 13 8192 yapar), yani kısaca ben olsam böyle bir yapıda zaten vector tercih ederdim ki zaten communityde şöyle bir terim var "almost always vector" yani ne kullanacağını bilmiyorsan `std::vector` kullan, %90 işini fazlasıyla görecektiri.

ama ben yine de iyi/kötü bir şey diyemem hele kod kalitesine falan hiç girmiyorum, zaten "yow metin2 için bu kadar kasılır mı yow 20 senelik oyun yow" bakış açısıyla hareket edilen bir ekosistemde DOD, bilgisayar bilimleri gibi konuları konuşmak maalesef duvara konuşmakla aynı şey, boşa efor.

çok meraklıysanız optimizasyona, en en basitinden code-basede "compile time" da yapılabilecek onlarca şey var, ama metin2de "iyi" bir tasarım asla olamaz oyun alanında iyi kişiler tarafından rewrite edilmediği sürece, topluluk "martysama vs owsap vs ikarus" diye konuşuyor, metin2 topluluğunda C++, hadi dili geçtim bilgisayar bilimleri vb. alanlarda bilgi düzeyi aşırı aşırı kısıtlı(biraz nefret cümlesi gibi ama herkes çok bilgili nasılsa kimse alınmaz) kimsenin hiçbir şey bilmediği bir yerde biri her şeyi bilebilir durumu gibi düşünün.

"kanka kod çalışıyor mu, çalışıyor" vizyonuyla ilerleyen bir kitleye (sadece metin2 değil savunmada dahi çalışan insanlarda da var bu) memory layout, zero-cost abstraction veya data locality anlatamazsın, kullanın yani bir zararını görmezsiniz, kağıt üzerinde arkadaş haklı, "unordered_map" aradığınız keyi "Hash-Table" olması sebebiyle constant timeda bulacaktır(worst case yaşanmaması durumunda). yazılımda her şey trade-off'tur, sadece kağıt üzeri düşünerek sığ bakılmamalı
 
Geri
Üst