工作总结之:优化函数调用

      最近相对比较有时间,于是想把代码整理一下,重构:永无止境.

         去年的时候,SOCKET用的是ACE,因为是公司用了很长时间的一个框架, 也就没细想,直接拿来过来用。但虫虫和棋牌不同:服务器要处理的数据量完全不是一个级别,而公司包装过的ACE竟然使用的是阻塞模式。于是,一个风高月黑的晚上,服务器卡得动弹不得。为了查这个BUG,我将所有的比较复杂的函数都加了时间跟踪, 也就是跟踪这个函数执行倒的花了多少时间。

        代码中有这么一个逻辑:扫描所有的房间,找出最合适的一个。一个服务器默认开1K个房间,这么简单逻辑应不至于太慢吧(默认执行时间0.001秒为报警下限),但倒的有多慢吧,我想,不会超过0.0001秒,于是,把报警下限设置成0.0001秒,也没多想,就更新到线上去了。

        新版本上线,习惯会跟踪一下,结果让大吃一惊:单个服务器,一天之内收到了4W多条告警。

        以下是我旧版的代码:         

{

NET_TIME_TRACE_POINT(RoomMgr::MatchRoom,0);

 

int  nLastLevelDiff = INT_MAX;

staticconst int MATCH_LEVEL_FACTOR = 2;

 

for(Rooms_type::iterator roomIt = m_RoomList.begin(); roomIt != m_RoomList.end();++roomIt)

{

if(excluderoom != (*roomIt)->GetID() && (*roomIt)->GetStatus() ==Room::ROOM_STATUS_HOLD && (*roomIt)->getRoomType() == roomtype&& (*roomIt)->getMaxPlayer() > (*roomIt)->GetPlayerCount())

{

constint nLevelDiff = abs((*roomIt)->getAvgLevel() - playerlevel);

if(nLevelDiff  < MATCH_LEVEL_FACTOR)

{

//等级相差2级之内,直接匹配成功.

room= *roomIt;

break;

}

elseif (nLevelDiff < nLastLevelDiff)

{

//否则匹配一个等级差最近的房间.

nLastLevelDiff= nLevelDiff;

room= *roomIt;

}

}

}

 

//因为房间为空时,房间类型为 Room::ROOM_TYPE_2VS2.

if(room == NULL && roomtype == Room::ROOM_TYPE_1VS1)

{

room= this->GetEmptyRoom();

}

}

以下是在本地测试时的日志输出, 足足花了270ns, 我一直以为这样的函数,以目前CPU的运算能力,执行时间可以忽略不计。时间倒的花在什么地方呢?

<TIME_TRACEname='RoomMgr::MatchRoom' Span='0.000270'/>

 

         Rooms_type 是一个 std::vector容器, std::vector迭代的速度是所有STL容器里面最快的,理应不会出问题,死马当活马医吧,于是,马上改写了一个数组版本,在本地服务器上一跑,很失望, std::vector 容器版本比数组版本要慢50ns左右, 但整个函数的开销还在200ns以上。同时也发现一个有趣的现像,std::vector 使用迭代器来迭代比反向迭代器要快,并且比使用下标的版本也要快。

1 . for (Rooms_type::size_type i = 0 ; i < m_RoomList.size();++i)     //使用下标来迭代

2 . for(Rooms_type::reverse_iterator roomIt = m_RoomList.rbegin(); roomIt !=m_RoomList.rend(); ++roomIt)   // 使用反向迭代器来迭代

3 . for (Rooms_type::iterator roomIt = m_RoomList.begin(); roomIt!= m_RoomList.end(); ++roomIt)   //使用正向迭代器来迭代        

 

        如果迭代一个数组,什么也不做,只花了6ns的时间。天啦,200ns的时间难道有花在那么简单的几个函数调用和值比较上了?也就是下面这个语句花了那200+ns中的大部份时间

      if (excluderoom != (*roomIt)->GetID()&& (*roomIt)->GetStatus() == Room::ROOM_STATUS_HOLD &&(*roomIt)->getRoomType() == roomtype && (*roomIt)->getMaxPlayer()> (*roomIt)->GetPlayerCount())

       于是,又马上改了一个新的版本

if((*roomIt)->MatchRoom(roomtype, excluderoom))

      以下为测试日志:

<TIME_TRACEname='RoomMgr::MatchRoom_fun' Span='0.000075'/>

<TIME_TRACEname='RoomMgr::MatchRoom_array' Span='0.000086'/>

      RoomMgr::MatchRoom_fun 使用的是STD::VECTOR,RoomMgr::MatchRoom_array 使用的是数组。无论那个版本都比老版本快了近4倍。

而且STD::VECTOR只比数组版慢了9ns, 因此STD::VECTOR对一般的应用来说,足够的快了!

 

       小结:

         在一个非常繁忙的函数中减少函数调次数会给你节省一些时间。

         就本次代码重构而言,根本算不上优化,而只是不进行劣化。有很多很牛的匹配算法,但我不想让这代码变得更复杂,更因为这个算法足够快了。

         一个函数的执行花了0.001s,我并不认为这会有什么性能问题,如果这个函数不是非常频繁地调用。

         80%的时间花在执行20%的代码里面,严格测试,找出关键的性能瓶颈,再优化,这才是王道。

         STL这玩意,很快,至少在LIUNX vector 如此。

      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值