日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

hashmap::begin() 坑

發(fā)布時間:2025/3/21 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hashmap::begin() 坑 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

因業(yè)務(wù)需要, 使用stl中的list+hashmap實現(xiàn)了一個容器做緩存;支持lru特性、? 支持O(1)時間的push_back, pop_head, find/delete。


大概實現(xiàn)是 將hashmap的iterator的關(guān)鍵部分作為list的元素; 將list的iterator的關(guān)鍵部分作為hashmap的value的其中一部分。 hashmap是真正存放數(shù)據(jù)的。

這樣能夠狠容易的從hashmap::iterator中解析得到對應(yīng)的list::iterator, 也能夠狠容易的從list::iterator解析得到對應(yīng)的hashmap::iterator。

其中后者代碼如下:

inline typename HashType::iterator LitToHit(typename ListType::iterator &it){//static typename HashType::iterator hit = m_hash.begin();//只是重用其中的_M_ht_List_node<ListKeyType> * lnode = static_cast<_List_node<ListKeyType> *>(it._M_node);hit._M_cur = lnode->_M_data;return hit;}
這個函數(shù)用的非常頻繁。 測試中發(fā)現(xiàn)這個函數(shù)非常影響性能,當(dāng)時十分不理解, 以為就是很簡單的O(1)而已。 仔細(xì)看代碼之后才發(fā)現(xiàn)其中玄機。

hashmap一維是個指針數(shù)組, 數(shù)組元素指向沖突處理鏈表。begin遍歷該數(shù)組, 返回第一個指針非空的數(shù)組下標(biāo)指向的數(shù)據(jù)節(jié)點。 當(dāng)元素較少時, begin可能會非常慢、一直遍歷到數(shù)組尾部才能找到第一個數(shù)據(jù)節(jié)點。

解決方法是使用static變量即可。



代碼如下,以后會有很多地用到,貼出以做備忘。

#pragma once//queue。 插入時key唯一。 O(1)的pushback, pophead, find/delete#include <list> #include <ext/hash_map>using namespace std; using namespace __gnu_cxx;template <typename Key, typename Value> class UniqQueue { public:class ValueNode;typedef hash_map<Key, ValueNode> HashType;typedef _Hashtable_node<pair<const Key, ValueNode> > * ListKeyType;typedef list<ListKeyType> ListType;typedef Key KeyType;typedef Value ValueType;typedef UniqQueue ThisType;class ValueNode{public:_List_node<ListKeyType> *list; // lru鏈表中的位置Value value; // 元素ValueNode():list(NULL), value() {}ValueNode(const ValueNode &r):list(r.list), value(r.value){}private:ValueNode &operator=(const ValueNode &r);//disable};private: HashType m_hash;ListType m_list;pthread_mutex_t m_lock;pthread_cond_t m_cond;public:UniqQueue():m_hash(1000000){pthread_cond_init(&m_cond, NULL);pthread_mutex_init(&m_lock, NULL);}~UniqQueue(){pthread_cond_destroy(&m_cond);pthread_mutex_destroy(&m_lock);}pthread_mutex_t & lock(){return m_lock;}void push_back(const Key & k, const Value &content){ pthread_mutex_lock(&m_lock);pair<typename HashType::iterator, bool> it = m_hash.insert(make_pair(k, ValueNode()));it.first->second.value = content;if(it.second == true)//cache中新加的數(shù)據(jù){ typename ListType::iterator lii = m_list.insert(m_list.end(), GetListNode(it.first));SetList(it.first, lii);}else{}pthread_cond_signal(&m_cond);pthread_mutex_unlock(&m_lock);return;}Value peak_head(){Value vn;typename ListType::iterator lii;typename HashType::iterator hit;// pthread_cleanup_push(Cleanup, this);pthread_mutex_lock(&m_lock);while(m_list.size() == 0){pthread_cond_wait(&m_cond, &m_lock);}lii = m_list.begin();hit = LitToHit(lii);//can not define Value vn; here.. because of cond_wait?? vn = hit->second.value;pthread_mutex_unlock(&m_lock);// pthread_cleanup_pop(0);return vn;}Value peak_head_nolock(){Value vn;typename ListType::iterator lii = m_list.begin();typename HashType::iterator hit = LitToHit(lii);vn = hit->second.value;return vn;}Value find(const Key &k){Value v;pthread_mutex_lock(&m_lock);typename HashType::iterator it = m_hash.find(k);if(it == m_hash.end()) ;elsev = it->second.value;pthread_mutex_unlock(&m_lock);return v;}void pop_head(bool want = true){if(want) pthread_mutex_lock(&m_lock);typename ListType::iterator lii = m_list.begin();typename HashType::iterator hit = LitToHit(lii);m_list.erase(lii);m_hash.erase(hit);if(want) pthread_mutex_unlock(&m_lock);}private://lock helperstatic void Cleanup(void *arg){ThisType *tis = (ThisType *)arg;pthread_mutex_unlock(&(tis->m_lock));}private: //iterator tool functionsinline ListKeyType GetListNode(typename HashType::iterator &v){return v._M_cur;}inline typename HashType::iterator LitToHit(typename ListType::iterator &it){static typename HashType::iterator hit = m_hash.begin();//只是重用其中的_M_ht_List_node<ListKeyType> * lnode = static_cast<_List_node<ListKeyType> *>(it._M_node);hit._M_cur = lnode->_M_data;return hit;}inline void SetList(typename HashType::iterator &v, typename ListType::iterator it){v->second.list = static_cast<_List_node<ListKeyType> * >(it._M_node);} };
當(dāng)時測試場景:

1寫線程從1開始遞增key,不停得push_back;? 1讀線程不停的peak_head+pop_head。

異常現(xiàn)象:

1)push_back線程的pthread_mutex_lock獲取鎖操作時間越來越長, 從0-1us變?yōu)閹资畟€ms。

2)peak_head+pop_head非常消耗cpu,幾乎吃滿cpu。 而寫線程只占30%左右的cpu。

3)內(nèi)存用完后變得更慢, push_back大概每秒只能push 30個左右。

4)其他等等

當(dāng)時百思不得其解,甚至懷疑pthread contidion的效率、 系統(tǒng)環(huán)境有問題。

其實1和2都已經(jīng)明確的指向了同一個問題了。 1獲取鎖慢, 肯定是其他線程持有鎖的時間長導(dǎo)致的。 2吃滿cpu,正好說明獲取鎖后做大量運算需要時間長。

就是peadk_head慢。 慢在哪, 仔細(xì)分析就是hashmap::begin慢



總結(jié)

以上是生活随笔為你收集整理的hashmap::begin() 坑的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产区视频 | 爱爱爱爱网站 | 欧美第五页 | 久久涩涩| 亚洲久久在线 | 97av视频 | www.黄色.| 欧美丰满美乳xxⅹ高潮www | 狠狠狠狠狠狠干 | 欧美乱妇视频 | 欧美香蕉| 91羞羞网站| 美国av大片 | 懂色av中文字幕 | 久久久资源 | 日本黄色片 | 久久大陆 | 免费看片色 | 久草资源在线视频 | 欧美aaa级 | 国产精品日 | 手机成人在线视频 | 91亚洲视频在线观看 | 亚洲最大中文字幕 | 免费h片网站| 日韩tv | 国产在线不卡av | 欧美黑粗硬 | 草草影院地址 | 美女啪啪免费视频 | 久久一久久 | 日本韩国欧美 | 9色视频在线观看 | 亚洲自拍偷拍精品 | 91桃色视频| 可以免费看的黄色网址 | 久久99精品久久只有精品 | 午夜爽爽影院 | 骚婷婷| 91超碰在线免费观看 | 日韩小视频在线观看 | 中文字幕视频免费 | 精品国产18久久久久久二百 | 爆乳熟妇一区二区三区霸乳 | 在线观看涩涩 | 人妻av一区二区 | 日日噜噜夜夜狠狠久久波多野 | 糖心vlog精品一区二区 | 日韩亚州 | 国产精品有码 | 成人福利视频在线观看 | 91亚洲国产成人久久精品网站 | 一本色道久久综合亚洲精品 | 欧美亚洲二区 | 午夜电影你懂的 | 国产做爰高潮呻吟视频 | 台湾性dvd性色av | 色噜噜一区二区 | 91叉叉叉 | 成人无高清96免费 | 久一在线 | 美女扒开腿让男人捅 | 免费涩涩 | 国产又粗又猛又爽又黄91精品 | 91网视频 | 奇米影视首页 | 久久资源总站 | 日韩香蕉视频 | 亚洲一区日韩精品 | 男女做受视频 | 二十四小时在线更新观看 | 激情噜噜 | 人妻丰满熟妇av无码久久洗澡 | 日韩在线观看av | 日韩av一二区 | 可以直接在线观看的av | 在线观看亚洲天堂 | 欧美综合亚洲图片综合区 | 国产高清毛片 | 美女扒开腿让男生捅 | 丁香婷婷深情五月亚洲 | 99久久久国产精品无码免费 | 青娱乐国产在线 | 免费在线看污视频 | 中文字幕一区二区三区免费视频 | 久久久久女人精品毛片九一 | 亚洲高清在线免费观看 | 尤物av无码色av无码 | 黑人精品一区二区 | 成熟了的熟妇毛茸茸 | 欧洲激情网| 怡春院视频 | 欧美一级片在线观看 | 日日摸夜夜添狠狠添欧美 | ass极品水嫩小美女ass | 日日燥夜夜燥 | 亚洲交性网 | av免费片 | 一曲二曲三曲在线观看中文字幕动漫 |