以前的服務端是win32平臺,STLport-5.1.4,boost-1.34.1,asio-0.3.8,apr的內存管理,消息池用的是MSMQ。
構架是loginserver,accountdb,gate,gamedb,gameserver,數據流向是:帳號密碼->loginserver->accountdb->loginserver->client->選區->gate->gamedb->gate->client->選人->gate->gameserver
先說說現在的問題,win32平臺就不說了^_^,也不談stlport boost的效率問題,msmq也中規中矩,主要是apr的問題,使用的是這樣的形式來做的內存管理
1 struct cUser
2 {
3 apr_pool_t* pool;
4
5 char name[25];
6 ushort level;
7 
8 };
9
10 // 申請
11 apr_pool_t* pool = 0;
12 apr_pool_create(_mainpool, &pool);
13 cUser* user = (cUser*)apr_pcalloc(pool, sizeof(cUser));
14 user->pool = pool;
15 strcpy_s(user->name, "test");
16 user->level = 0;
17
18 // 釋放
19 if (user)
20 {
21 if (user->pool)
22 apr_pool_destory(user->pool);
23 }
服務端運行過程中很偶爾會出現user->pool為空,因為釋放是程序結束時統一釋放,所以沒有理由懷疑釋放錯誤,只能是內存越界,比如
1 apr_pool_t* pool = 0;
2 apr_pool_create(mainpool, &pool);
3
4 cUser* user = (cUser*)apr_pcalloc(pool, sizeof(cUser) * 20);
5
6 for (int i = 0; i < 20; i++)
7 user[i].pool = pool;
8
9 // 這只是個示例,當然不會有人這么做
10 // 假設cUser最后一個變量是 char temp[100];
11 struct cUser
12 {
13 apr_pool_t* pool;
14
15 char name[25];
16 ushort level;
17 char temp[100];
18 };
19 memcpy(user[0].temp, "test", 104);
20 // 這個時候user[1]的pool就是空的了。
因為構架是我做的,具體邏輯不是我寫的,在幾十萬行代碼里一點一點跟哪里出錯實在太渺茫,而且有點懷疑apr內部是否有bug,因為看錯誤的內存,明顯整個user都是被apr_pool_destroy掉的。so。。這次不用apr了,那么大個庫使用一個apr_pool是有點殺雞牛刀的感覺。
這次簡簡單單定義
void* mem_alloc(size_t size);
void* mem_realloc(void* p, size_t size);
void mem_free(void* p);
// 實現
void* mem_alloc(size_t size)
{
void* p = 0;
p = malloc(size);
#ifdef _DEBUG
if (p)
memset(p, 0, size);
#endif
return p;
}
void* mem_realloc(void* p, size_t size)
{
void* p = 0;
p = realloc(p, size);
return p;
}
void mem_free(void* p)
{
if (p)
{
free(p);
p = 0;
}
}
當然后面打算帶上gc,暫時直接申請內存方便valgrind挑錯。
構架的問題就大了,一開始的設計是單loginserver多gate,單gate對單gameserver,后來發現一個gameserver帶30幾張地圖,跑5000+npc簡直就是自殘,于是改,改單gate帶多gameserver,問題來了,我們的構架是gamedb只和gate聯系,一旦跨地圖組隊,user信息就要從一個gameserver帶到gate再發給另一個gameserver,以前只考慮了由gate保存user信息,gameserver只是一份copy,更新數據方便,但是現在gate的負擔超級重。
還有數據庫問題,用的oracle,oci直接操作,accountdb沒問題,gamedb是來了請求就去數據庫拿或者寫,沒有做user的緩存,而且是整個user結構體帶來帶去,通信量特別大。結果是經常報告statement操作的游標過多,提高oracle的64個游標數量只是暫時解決方案。經常選了服就卡住,拿不到人物信息。
最主要就是msmq輪詢取消息process的時候沒有用阻塞模式(或者沒有阻塞模式?)
1 if (0 == MSMQGetMessage(
))
2 {
3 Sleep(1);
4 }
5 else
6 {
7 Process_Packet(
);
8 }
問題出在這個sleep(1)上了,不sleep,4個msmq線程,npc的process被搶的什么都干不成,sleep的話cpu就死活利用不上去。懶得找msmq的阻塞模式了。
還有就是設計上的問題了,比如
1 struct User_Save_Info
2 {
3 char name[25];// 沒問題,12個中文字的名字。
4 int gender;// 性別,大哥,你有42億種性別么?
5 int facestyle;// 臉型,同上
6 int hairstyle;// 發型,同上
7
// 后面類似的不說了。
8 };
我就說策劃大哥們,我為了省包頭的2字節絞盡腦汁,你們可好。。。無語了。。。
Item_Info_Save是存裝備的,我們的裝備有隨機屬性,但是他們居然把裝備的通用屬性都由服務器來發,最郁悶的是設計npc死亡掉落物品數量達到50件。。。就是一個npc死亡,我需要發8(小隊人數)*50(裝備個數)*sizeof(Item_Info_Save)(這個sizeof至少100字節)。。。
ok問題暫時說到這里,下一貼說重構后的改動。
posted on 2008-04-09 00:01
大日如來 閱讀(2465)
評論(10) 編輯 收藏 引用 所屬分類:
游戲-編程