Ram kullanım oranını %70 düşürün

  • Konbuyu başlatan Konbuyu başlatan Admin
  • Başlangıç tarihi Başlangıç tarihi
  • Cevaplar Cevaplar 0
  • Görüntüleme Görüntüleme 44

Admin

Metin2Lobby
Yönetici
Founder
Katılım
6 Mayıs 2022
Mesajlar
52,647
Ticaret : 1 / 0 / 0
Sorun:
Canavarlar,Simyalar, öğeler vb. için sabit boyutlu diziler içeren CHARACTER_POINT_INSTANT yapısını kullanılıyor. Her canavar için bu diziler bellek ayırıyor, ancak canavarlar bu belleği kullanmıyor...

Çözüm:
Sabit boyutlu dizileri std::map veya diğer veri türleri ile değiştirin
Kendi testlerime göre, özel envanter sistemi ve aşağıda listelenen optimize edilmiş değişkenlerle bellek kullanımında %70'in üzerinde azalma gördüm:



Kod:
//in char.cpp at the end of void CHARACTER::Initialize() function add [HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP m_pointsInstant.pItemsGridMap.clear(); [HASH=3]#endif[/HASH] //in char.h after function LPITEM GetInventoryItem add [HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP     BYTE    ItemGridMapGetConst(BYTE cell_index) const; [HASH=3]#endif[/HASH] //in char.h replace BYTE bItemGrid[INVENTORY_AND_EQUIP_SLOT_MAX]; with   [HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP     std::map<BYTE, BYTE> pItemsGridMap; [HASH=2311]#else[/HASH]     BYTE bItemGrid[INVENTORY_AND_EQUIP_SLOT_MAX]; [HASH=3]#endif[/HASH]   //in char_item.cpp replace function CHARACTER::SetItem with   void CHARACTER::SetItem(TItemPos Cell, LPITEM pItem) {     WORD wCell = Cell.cell;     BYTE window_type = Cell.window_type;     if ((unsigned long)((CItem*)pItem) == 0xff || (unsigned long)((CItem*)pItem) == 0xffffffff)     {         sys_err("!!! FATAL ERROR !!! item == 0xff (char: %s cell: %u)", GetName(), wCell);         core_dump();         return;     }     if (pItem && pItem->GetOwner())     {         assert(!"GetOwner exist");         return;     }       switch(window_type)     {     case INVENTORY:     case EQUIPMENT:         {             if (wCell >= INVENTORY_AND_EQUIP_SLOT_MAX)             {                 sys_err("CHARACTER::SetItem: invalid item cell %d", wCell);                 return;             }             LPITEM pOld = m_pointsInstant.pItems[wCell];             if (pOld)             {                 if (wCell < INVENTORY_MAX_NUM)                 {                     for (int i = 0; i < pOld->GetSize(); ++i)                     {                         int p = wCell + (i * 5);                         if (p >= INVENTORY_MAX_NUM)                             continue;                         if (m_pointsInstant.pItems[p] && m_pointsInstant.pItems[p] != pOld)                             continue; [HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP                         m_pointsInstant.pItemsGridMap[p] = 0; [HASH=2311]#else[/HASH]                         m_pointsInstant.bItemGrid[p] = 0; [HASH=3]#endif[/HASH]                     }                 }                 else [HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP                     m_pointsInstant.pItemsGridMap[wCell] = 0; [HASH=2311]#else[/HASH]                     m_pointsInstant.bItemGrid[wCell] = 0; [HASH=3]#endif[/HASH]             }             if (pItem)             {                 if (wCell < INVENTORY_MAX_NUM)                 {                     for (int i = 0; i < pItem->GetSize(); ++i)                     {                         int p = wCell + (i * 5);                         if (p >= INVENTORY_MAX_NUM)                             continue;                        [HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP                         m_pointsInstant.pItemsGridMap[p] = wCell + 1; [HASH=2311]#else[/HASH]                         m_pointsInstant.bItemGrid[p] = wCell + 1; [HASH=3]#endif[/HASH]                     }                 }                 else [HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP                     m_pointsInstant.pItemsGridMap[wCell] = wCell + 1; [HASH=2311]#else[/HASH]                     m_pointsInstant.bItemGrid[wCell] = wCell + 1; [HASH=3]#endif[/HASH]             }             m_pointsInstant.pItems[wCell] = pItem;         }         break;     case DRAGON_SOUL_INVENTORY:         {             LPITEM pOld = m_pointsInstant.pDSItems[wCell];             if (pOld)             {                 if (wCell < DRAGON_SOUL_INVENTORY_MAX_NUM)                 {                     for (int i = 0; i < pOld->GetSize(); ++i)                     {                         int p = wCell + (i * DRAGON_SOUL_BOX_COLUMN_NUM);                         if (p >= DRAGON_SOUL_INVENTORY_MAX_NUM)                             continue;                         if (m_pointsInstant.pDSItems[p] && m_pointsInstant.pDSItems[p] != pOld)                             continue;                         m_pointsInstant.wDSItemGrid[p] = 0;                     }                 }                 else                     m_pointsInstant.wDSItemGrid[wCell] = 0;             }             if (pItem)             {                 if (wCell >= DRAGON_SOUL_INVENTORY_MAX_NUM)                 {                     sys_err("CHARACTER::SetItem: invalid DS item cell %d", wCell);                     return;                 }                 if (wCell < DRAGON_SOUL_INVENTORY_MAX_NUM)                 {                     for (int i = 0; i < pItem->GetSize(); ++i)                     {                         int p = wCell + (i * DRAGON_SOUL_BOX_COLUMN_NUM);                         if (p >= DRAGON_SOUL_INVENTORY_MAX_NUM)                             continue;                         m_pointsInstant.wDSItemGrid[p] = wCell + 1;                     }                 }                 else                     m_pointsInstant.wDSItemGrid[wCell] = wCell + 1;             }             m_pointsInstant.pDSItems[wCell] = pItem;         }         break;     default:         sys_err ("Invalid Inventory type %d", window_type);         return;     }     if (GetDesc())     {         if (pItem)         {             TPacketGCItemSet pack;             pack.header = HEADER_GC_ITEM_SET;             pack.Cell = Cell;             pack.count = pItem->GetCount();             pack.vnum = pItem->GetVnum();             pack.flags = pItem->GetFlag();             pack.anti_flags    = pItem->GetAntiFlag();             pack.highlight = (Cell.window_type == DRAGON_SOUL_INVENTORY);             thecore_memcpy(pack.alSockets, pItem->GetSockets(), sizeof(pack.alSockets));             thecore_memcpy(pack.aAttr, pItem->GetAttributes(), sizeof(pack.aAttr));             GetDesc()->Packet(&pack, sizeof(TPacketGCItemSet));         }         else         {             TPacketGCItemDelDeprecated pack;             pack.header = HEADER_GC_ITEM_DEL;             pack.Cell = Cell;             pack.count = 0;             pack.vnum = 0;             memset(pack.alSockets, 0, sizeof(pack.alSockets));             memset(pack.aAttr, 0, sizeof(pack.aAttr));             GetDesc()->Packet(&pack, sizeof(TPacketGCItemDelDeprecated));         }     }     if (pItem)     {         pItem->SetCell(this, wCell);         switch (window_type)         {         case INVENTORY:         case EQUIPMENT:             if ((wCell < INVENTORY_MAX_NUM) || (BELT_INVENTORY_SLOT_START <= wCell && BELT_INVENTORY_SLOT_END > wCell))                 pItem->SetWindow(INVENTORY);             else                 pItem->SetWindow(EQUIPMENT);             break;         case DRAGON_SOUL_INVENTORY:             pItem->SetWindow(DRAGON_SOUL_INVENTORY);             break;         }     } } [HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP BYTE CHARACTER::ItemGridMapGetConst(BYTE cell_index) const {     auto it = m_pointsInstant.pItemsGridMap.find(cell_index);     if (it != m_pointsInstant.pItemsGridMap.end())     {         return it->second;     }     else     {         return 0;     } } [HASH=3]#endif[/HASH]   //in char_item.cpp replace function CHARACTER::IsEmptyItemGrid with bool CHARACTER::IsEmptyItemGrid(TItemPos Cell, BYTE bSize, int iExceptionCell) const {     switch (Cell.window_type)     {     case INVENTORY:         {             BYTE bCell = Cell.cell;             ++iExceptionCell;             if (Cell.IsBeltInventoryPosition())             {                 LPITEM beltItem = GetWear(WEAR_BELT);                 if (NULL == beltItem)                     return false;                 if (false == CBeltInventoryHelper::IsAvailableCell(bCell - BELT_INVENTORY_SLOT_START, beltItem->GetValue(0)))                     return false; [HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP                 if (ItemGridMapGetConst(bCell))                 {                     if (ItemGridMapGetConst(bCell) == iExceptionCell)                         return true;                     return false;                 } [HASH=2311]#else[/HASH]                 if (m_pointsInstant.bItemGrid[bCell])                 {                     if (m_pointsInstant.bItemGrid[bCell] == iExceptionCell)                         return true;                     return false;                 } [HASH=3]#endif[/HASH]                 if (bSize == 1)                     return true;             }             else if (bCell >= INVENTORY_MAX_NUM)                 return false; [HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP             if (ItemGridMapGetConst(bCell))             {                 if (ItemGridMapGetConst(bCell) == iExceptionCell) [HASH=2311]#else[/HASH]             if (m_pointsInstant.bItemGrid[bCell])             {                 if (m_pointsInstant.bItemGrid[bCell] == iExceptionCell) [HASH=3]#endif[/HASH]                 {                     if (bSize == 1)                         return true;                     int j = 1;                     BYTE bPage = bCell / (INVENTORY_MAX_NUM / 2);                     do                     {                         BYTE p = bCell + (5 * j);                         if (p >= INVENTORY_MAX_NUM)                             return false;                         if (p / (INVENTORY_MAX_NUM / 2) != bPage)                             return false; [HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP                         if (ItemGridMapGetConst(p))                             if (ItemGridMapGetConst(p) != iExceptionCell)                                 return false; [HASH=2311]#else[/HASH]                         if (m_pointsInstant.bItemGrid[p])                             if (m_pointsInstant.bItemGrid[p] != iExceptionCell)                                 return false; [HASH=3]#endif[/HASH]                        }                     while (++j < bSize);                     return true;                 }                 else                     return false;             }             if (1 == bSize)                 return true;             else             {                 int j = 1;                 BYTE bPage = bCell / (INVENTORY_MAX_NUM / 2);                 do                 {                     BYTE p = bCell + (5 * j);                     if (p >= INVENTORY_MAX_NUM)                         return false;                     if (p / (INVENTORY_MAX_NUM / 2) != bPage)                         return false; [HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP                     if (ItemGridMapGetConst(p))                         if (ItemGridMapGetConst(p) != iExceptionCell)                             return false; [HASH=2311]#else[/HASH]                     if (m_pointsInstant.bItemGrid[p])                         if (m_pointsInstant.bItemGrid[p] != iExceptionCell)                             return false; [HASH=3]#endif[/HASH]                 }                 while (++j < bSize);                 return true;             }         }         break;     case DRAGON_SOUL_INVENTORY:         {             WORD wCell = Cell.cell;             if (wCell >= DRAGON_SOUL_INVENTORY_MAX_NUM)                 return false;             iExceptionCell++;             if (m_pointsInstant.wDSItemGrid[wCell])             {                 if (m_pointsInstant.wDSItemGrid[wCell] == iExceptionCell)                 {                     if (bSize == 1)                         return true;                     int j = 1;                     do                     {                         BYTE p = wCell + (DRAGON_SOUL_BOX_COLUMN_NUM * j);                         if (p >= DRAGON_SOUL_INVENTORY_MAX_NUM)                             return false;                         if (m_pointsInstant.wDSItemGrid[p])                             if (m_pointsInstant.wDSItemGrid[p] != iExceptionCell)                                 return false;                     }                     while (++j < bSize);                     return true;                 }                 else                     return false;             }             if (1 == bSize)                 return true;             else             {                 int j = 1;                 do                 {                     BYTE p = wCell + (DRAGON_SOUL_BOX_COLUMN_NUM * j);                     if (p >= DRAGON_SOUL_INVENTORY_MAX_NUM)                         return false; [HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP                     if (ItemGridMapGetConst(p)) [HASH=2311]#else[/HASH]                     if (m_pointsInstant.bItemGrid[p]) [HASH=3]#endif[/HASH]                         if (m_pointsInstant.wDSItemGrid[p] != iExceptionCell)                             return false;                 }                 while (++j < bSize);                 return true;             }         }     } }

Ram Kullanım Oranını %70 Düşürmek İçin Metin2 Sunucu Performans Optimizasyonları

Metin2 özel sunucularında performans optimizasyonu yaparken karşılaşılan en yaygın sorunlardan birisi yüksek RAM tüketimidir. Bu yazıda, Metin2 özel sunucu geliştirme sürecinde RAM kullanım oranını %70 oranında düşürebileceğiniz teknikleri detaylıca ele alacağız.

RAM Tüketimini Etkileyen Faktörler

Metin2 özel sunucularında RAM tüketimi, genellikle oyun motoru, veritabanı işlemleri, aktif oyuncuların sayısı ve sunucudaki sistemsel yapılandırmalar gibi birçok faktöre bağlıdır. Özellikle game server ve auth server yapılandırmalarında yapılan küçük eksiklikler bile RAM üzerinde ciddi artışlara neden olabilir. Bu durumda, sunucu çökmesi veya yavaşlama gibi ciddi problemlerle karşılaşılabilir.

Sunucu Kaynak Kodlarında RAM Optimizasyonu

Metin2 sunucu kaynak kodları genellikle C++ diliyle yazılmıştır. Bu kaynak kodların RAM üzerindeki etkisi büyük ölçüdedir. Özellikle memory leak (bellek sızıntısı) gibi problemler, uzun süre çalışan sunucularda RAM kullanımının artmasına yol açar. Martysama veya diğer popüler sunucu yapıları kullanılırken, kodda bulunan her new ifadesi için karşılık gelen delete işleminin yapılması kritik öneme sahiptir. Ayrıca, std::vector, std::map gibi yapılar kullanılırken kapasite yönetimi dikkatlice yapılmalıdır.

Veritabanı (DB) Optimizasyonu

Metin2 sistemlerinde DB işlemleri RAM üzerinde dolaylı ama önemli bir etkiye sahiptir. Oyuncu verileri, envanter içerikleri, guild bilgileri gibi verilerin sık sık veritabanına yazılması ve okunması RAM üzerinde işlem yükünü artırır. Connection pooling teknikleri kullanarak, veritabanı bağlantılarını tekrar tekrar oluşturma ihtiyacını ortadan kaldırabilirsiniz. Bu sayede RAM tüketimi azaltılırken aynı zamanda sunucu yanıt süresi de iyileştirilir.

Python Sistemlerinde RAM Tasarrufu

Metin2 özel sunucularında bazı sistemler Python ile yazılmıştır. Örneğin py root dosyaları, uiscript dosyaları ve GUI sistemleri genellikle Python tabanlıdır. Bu sistemlerde RAM tasarrufu için memory profiling araçları kullanarak bellek sızıntılarını tespit edip düzeltebilirsiniz. Ayrıca, gereksiz obje yaratmaktan kaçınıp, garbage collector (çöp toplayıcı) sistemini etkin kullanarak RAM tüketimini düşürebilirsiniz.

Oyuncu Verilerini Geçici Belleğe Alma

Sunucu üzerinde aktif olan oyuncuların verilerini geçici olarak RAM üzerinde tutmak, veritabanı işlemlerini azaltarak performansı artırır. Ancak bu verilerin zamanında temizlenmemesi RAM tüketimini artırabilir. Bu yüzden cache mekanizmaları doğru şekilde ayarlanmalı ve zamanlayıcılarla temizlenmelidir. Özellikle channel bazında veri yönetimleri optimize edilmelidir.

Sunucu Ayarlarının Optimize Edilmesi

Sunucu yapılandırmasında yer alan bazı ayarlar RAM tüketimini doğrudan etkiler. Örneğin, max player sayısı, event frekansları, mob spawn aralıkları gibi ayarlar optimize edilerek RAM üzerindeki yük azaltılabilir. Game core ve db core yapılandırmaları da bu bağlamda gözden geçirilmelidir.

Sonuç

Metin2 özel sunucularında RAM kullanımını %70 oranında düşürmek, doğru kodlama, veritabanı yönetimi ve sunucu yapılandırması ile mümkündür. Özellikle C++ tabanlı sunucu kaynak kodları üzerinde yapılacak optimizasyonlar, RAM tüketimini ciddi şekilde düşürecektir. Py GUI ve diğer Python tabanlı sistemler için de benzer optimizasyonlar uygulanabilir. Bu tür geliştirmeler, hem sunucu kararlılığını artırır hem de oyuncular için daha akıcı bir deneyim sağlar.


Reducing RAM Usage by 70% for Metin2 Server Performance Optimization

One of the most common issues during performance optimization in Metin2 private servers is high RAM consumption. In this article, we will discuss technical methods to reduce RAM usage by up to 70% during Metin2 private server development in detail.

Factors Affecting RAM Consumption

In Metin2 private servers, RAM usage is generally influenced by several factors including the game engine, database operations, number of active players, and server-side configurations. Issues such as misconfigurations in game server and auth server setups can cause significant increases in RAM consumption, potentially leading to server crashes or slowdowns.

RAM Optimization in Server Source Code

Metin2 server source codes are primarily written in C++. These codes have a major impact on RAM usage. Memory leaks can significantly increase RAM usage over time on long-running servers. When using structures like Martysama or other popular server frameworks, ensuring every new statement has a corresponding delete is critical. Additionally, careful capacity management should be applied when using structures like std::vector and std::map.

Database (DB) Optimization

In Metin2 systems, DB operations have an indirect but significant effect on RAM. Frequent reading and writing of player data, inventory contents, guild information, etc., increases the processing load on RAM. By utilizing connection pooling techniques, you can eliminate the need to repeatedly create database connections, thereby reducing RAM consumption and improving server response times.

Saving RAM in Python Systems

Some systems in Metin2 private servers are coded in Python. For instance, py root, uiscript files, and GUI systems are usually Python-based. To save RAM in these systems, use memory profiling tools to detect and fix memory leaks. Also, avoid creating unnecessary objects and utilize the garbage collector effectively to reduce RAM usage.

Caching Player Data in Temporary Memory

Storing active player data temporarily in RAM reduces database operations, improving performance. However, failure to clean up this data timely may increase RAM usage. Therefore, cache mechanisms must be properly configured and cleaned periodically, especially for channel-based data management.

Optimizing Server Configurations

Certain server configuration settings directly affect RAM consumption. Settings like max player count, event frequencies, and mob spawn intervals can be optimized to reduce RAM load. Game core and db core configurations should also be reviewed in this context.

Conclusion

Reducing RAM usage by 70% in Metin2 private servers is achievable through proper coding, database management, and server configuration. Optimizations made in C++-based server source codes will significantly reduce RAM consumption. Similar optimizations can be applied to Py GUI and other Python-based systems. Such improvements enhance server stability and provide a smoother experience for players.
 

Şuan Bu Konuyu Görüntüleyen Kullanıcılar (Toplam : 0, Üye : 0, Misafir : 0)

Benzer konular

Geri
Üst Alt