seo常用优化技巧 网站代码优化工具( 四 )


相比哈希表和红黑树,跳表用的不那么多 。
### 数据结构的实现优化
我们通常只会讲数据的逻辑结构,但数据的实现(存储)结构也会影响性能 。
数组在存储上一定是逻辑地址连续的,但链表不具有这样的特点,链表通过链域寻找临近节点,如果相邻节点在地址上发散,则沿着链域访问效率不高,所以实现上可以通过从单独的内存配置器分配结点(尽量内存收敛)来优化访问效率,同样的方法也适应红黑树、哈希表等其他结构 。
### 排序
尽量对指针、索引、ID排序,而不要对对象本身排序,因为交换对象比交换地址/索引慢;求topN不要做全排序;非稳定排序能满足要求不要搞稳定排序 。
### 延迟计算 & 写时拷贝
延迟计算和写时拷贝(COW)思想上是一样的,即可以通过把计算尽量推迟来减少计算开销 。
我拿游戏服务器开发来举例,假设玩家的战斗力(fight)是通过等级,血量,称号等其他属性计算出来的,我们可以在等级、血量、称号变化的时候立即重算fight,但血量可能变化比较频繁,所以就会需要频繁重算战力 。通过延迟计算,我们可以为战力添加一个dirtyFlag,在等级、血量、称号变化的时候设置dirtyFlag,等到真正需要用到战力的时候(GetFight函数)里判断dirtyFlag,如果dirtyFlag为true则重算战力并清dirtyFlag,如果dirtyFlag为false则直接返回fight值 。
写时拷贝(COW)跟这个差不多,linux kernel在fork进程的时候,子进程会共享父进程的地址空间,只有在子进程对自身地址空间写的时候,才会clone一份出来,同样,string的设计也用到了类似的思想 。
### 预计算
有些值可以提前计算出结果并保存起来,不用重复计算的尽量不重复计算,特别是循环内的计算,要避免重复的常量计算,C++甚至增加了一个constexpr的关键词 。
### 增量更新
增量更新的原理不复杂,只做增量,只做DIFF,不做全量,这个思想有很多应用场景 。
举个例子,游戏服务器每隔一段时间需要把玩家的属性(比如血量、魔法值等)同步到客户端,简单的做法是把所有属性打包一次性全发送过去,这样比较耗费带宽,可以考虑为每个属性编号,在发送的时候,只发送变化的属性 。
在发送端,编码一个变化的属性的时候,需要发送一个属性编号+属性值的对子,接收端类似,先解出属性编号,再解出属性值,这种方式可能需要牺牲一点CPU换带宽 。
## 3、代码优化
### 内存优化
(a)小对象分配器
C的动态内存分配是介于系统和应用程序的中间层,malloc/free本身体现的就是一种按需分配+复用的思想 。
当你调用malloc向glibc的动态内存分配器ptmalloc申请6字节的内存,实际耗费的会大于6字节,6是动态分配块的有效载荷,动态内存分配器会为chunk添加首部和尾部,有时候还会加一下填充,所以,真正耗费的存储空间会远大于6字节,在我的机器上,通过malloc_usable_size发现申请6字节,返回的chunk,实际可用的size为24,加上首尾部就更多了 。
但你真正申请(可用)的大小是6字节,可见,动态内存分配的chunk内有大量的碎片,这就是内碎片,而外碎片是存在chunk之间的,是另一个问题 。
当你申请的size较大,有效载荷 / 耗费空间的比例会比较高,内碎片占比不高,但但size较小,这个占比就高,如果这种小size的chunk非常多,就会造成内存的极大浪费 。
《C++设计新思维》一书中的loki库实现了一个小对象分配器,通过隐式链表的方式解决了这个问题,有兴趣的可以去看看 。
(b)cached obj


以上关于本文的内容,仅作参考!温馨提示:如遇健康、疾病相关的问题,请您及时就医或请专业人士给予相关指导!

「四川龙网」www.sichuanlong.com小编还为您精选了以下内容,希望对您有所帮助: