使用unordered_map提升查找效率


 

在對網絡數據包流(Flow)進行處理的時候,一開始為了簡單使用了vector做為Flow信息的存儲容器,當其中的元素達到幾十萬時,程序的執行速度讓人無法忍受。已經對vector進行過合理的預先reserve,因為不是push_back的問題,而是查找。后改為unordered_map,對於同樣的數據,執行時間從3分40秒提高到10秒。

unordered_map應該是一個C++11特性,較舊的編譯器應該不支持。而VC++2012文檔中也提到廢棄了hash_map,而使用unordered_map。相關參考見http://www.cplusplus.com/reference/unordered_map/unordered_map

 

以下是代碼。

先編寫鍵結構,這里用的是俗稱的“五元組”:

struct flow_key
{
    int32   ipa;
    int32   ipb;
    uint16  porta;
    uint16  portb;
    uint32  proto;

    friend bool operator== (const flow_key& a, const flow_key& b);
};

 

  因為flow_key是自定義的鍵類型,因此除了上面的operator==,還需要實現hash函數,這里我是隨便寫的一個,發生沖突的機會應該相當高了,呵呵。據資料說,當hash函數結果相同時,則繼續調用operator==進行比較:

struct flow_hash
{
    size_t operator() (const flow_key& k) const
    {
        return k.ipa + k.ipb + k.porta + k.portb;
    }
};

  接下來編寫value結構,我用的是flow_info,代碼較多,就不貼了。

為了之后減小代碼敲入字數,我給以上述2者為key和value的unordered_map起了個別名:

typedef std::unordered_map<flow_key,  flow_info,  flow_hash>        flow_map_t;

我這里都用的值類型,沒用指針類型,也許能再快些,但指針帶來的煩惱也是有代價的,呵呵。

在使用此類型的地方,做如下聲明:

flow_map_t  m_flows;

OK了,可以用了。

在使用的過程中,如果要查找,代碼大概如下:

        pair<flow_map_t::iterator, bool> hash_ret;
        flow_map_t::iterator it = m_flows.find(fkey);

        if(it == m_flows.end())
        {
            // 沒找到,插入新項
            hash_ret = m_flows.insert(make_pair(fkey, flow));
            it = hash_ret.first;
        }

注意insert操作的返回類型哦,是一個pair,first是插入的對應的迭代器,second是bool值,指示插入是否成功。

我這里主要是還要進行一些額外操作,所以用了什么find之類,如果你不關心這個鍵是否已在map之中,只想沒有就插入,那直接進行insert操作就可以了,如果已經存在此鍵,則hash_ret的first就是已存在鍵的元素所對應的迭代器。

由於我需要以整數下標對流信息進行各種操作,所以我在得到完整的unordered_map之后,把它復制給了vector。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM