关于map使用的优化备忘

今天领导在review我代码时提出了一处优化点,其实写完后看感觉很简单,但是总觉得很有启发意义,做一下记录。

原始伪码

.h文件

1
2
3
4
5
6
7
8
class DataMgr {
/***
其他内容
***/
private:
std::map<uint32, std::map<uint32, A>> mapA;
std::map<uint32, std::map<uint32, B>> mapB;
};

.cpp文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void DataMgr::fillMsg(uint32 userId, uint32 subKey)
{
auto iter = mapA_.find(userId);
if(iter != mapA_.end()) {
auto iter2 = iter->second.find(subKey);
/***
* 使用iter2中A结构进行逻辑操作
***/
}

auto iter = mapB_.find(userId);
if(iter != mapB_.end()) {
auto iter2 = iter->second.find(subKey);
/***
* 使用iter2中B结构进行逻辑操作
***/
}
}

伪码未必完全一致和正确。要表达的意思是,数据管理类中有两个存放了不同数据的map。但其中两个map中key1,key2所代表意义是一样的。fillMsg是一个高频调用的函数。

发现问题并提出优化

其中mapA为原始存在的代码,mapB为我后续加的逻辑。当时一开始加了之后没太注意有一个如此类似的数据类,即使在我加完fillMsgmapB的片段以及别的使用逻辑后仍未发现。今天领导提出这点,没什么可说的,肯定是要做并且有必要作优化的。(即使一开始有点“嘴硬”觉得AB两个结构体在自然逻辑上不太那么说得通)

但之后仔细想想,fillMsg是广播某个高频协议所使用的数据填充函数,那么该方法调用频率会非常高,两层map本身查找就会带来开销,做两次key值一模一样的查找无疑是很丑陋的。此处合并两个map所带来的的效率提升要远高于自然逻辑上那么一点点说不通的弊端。

感想

其实近段时间由于修改基础层代码偏多,领导提出的优化意见也很多。今天这个其实要说多突出也说不上,但我自己是很认可,并且觉得是很有必要备忘的一个点。在数据管理类后续加类似key值相同的数据时,先观察原有代码是否有可以合并进去的类。以及在使用时注意高频接口代码编写的执行效率,多一次这种map级别的查找是很不应该出现的。

其实可能是上一个公司以及项目组或是对代码重构以及优化太不看重、或是本身那两年写的代码就不涉及太多高频以及底层逻辑,导致现在经常会犯或者说意识不到这类效率以及代码封装风格的问题。记一篇备忘,希望自己以后能在这方面做得更好一些。