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


《C++ Primer》实现了一个CachedObj类模板,任何需要拥有这种cached能力的类型都可以通过从CachedObj<T>派生而获得 。
它的主要思想是为该种类型维护一个FreeList,每个节点就是一个Object,对象申请的时候,检查FreeList,如果FreeList不为空,则摘除头结点返回,如果FreeList为空,则new一批Object并串到FreeList,然后走FreeList不为空的分配流程,通过重载类的operator new和operator delete,达到对类的使用者透明的目的 。
(c)内存分配和对象构建分离
c的malloc用来动态分配内存,free用来归还内存;C++的new做了3件事,通过operator new(本质上等同malloc)分配内存,在分配的内存上构建对象,返回对象指针;而delete干了两件事,调用析构函数,归还内存 。
C++通过placement new可以分离内存分配和对象构建,结合显示的析构函数调用,达到自控的目的 。
我优化过一个游戏项目,启动时间过长,记忆中需要几十秒(至少十几秒),分析后发现主要是因为游戏执行预分配策略(对象池),在启动的时候按最大容量创建怪和玩家,对象构建很重,大量对象构建耗时过长,通过分离内存分配和对象构建,把对象构建推迟到真正需要的时候,实现了服务的重启秒起 。
(d)内存复用
编解码、加解密、序列化反序列化(marshal/unmarshal)的时候一般都需要动态申请内存,这种调用频次很高,可以考虑用静态内存,为了避免多线程竞争,可以用thread local 。
当然你也可以改进静态内存策略,比如封装一个GetEncodeMemeory(size_t)函数,维护一个void* + size_t结构体对象(初始化为NULL+0),对比参数size跟对象的size成员,如果参数size<=对象size,直接返回对象大的void*指针,否则free掉void*指针,再按参数size分配一个更大的void*,并用参数size更新对象size 。
### cache优化
i-cache优化:i-cache的优化可以通过精简code path,简化调用关系,减少代码量,减少复杂度来实现 。
具体措施包括,减少函数调用(就地展开、inline),利用分支预测,减少函数指针,可以考虑把code path上相关的函数定义在一起,把相关的函数定义到一个源文件,并让它们在源文件上临近,这样生成的object文件,在运行时加载后相关函数大概率也内存临近,当然编译器也一直在做这方面的努力,但我们写代码不应该依赖编译器优化,尽量去帮助编译器生成更高效的代码 。
d-cache优化:d-cache优化包括改进数据结构和算法获取更好的数据访问时空局部性,比如二分查找就是d-cache友好算法 。一个cache line一般是64B,如果数据跨越两个cache-line,则会导致load & store2次,所以,需要结合cache对齐,尽量让相关访问的数据在一个cache-line 。
如果结构体过大,则各成员不仅可能在不同cache-line,甚至可能在不同page,所以应该避免结构体过大 。
如果结构体的成员变量过多,一般而言对各成员的访问频次也会满足2-8定律,可以考虑把hot和cold的成员分开,重排结构体成员变量顺序,但这些骚操作我不建议在开始的时候用,因为说不定哪天又要增删成员,从而破坏苦心孤诣搭建的积木 。
### 判断前置
判断前置指在函数中讲判断返回的语句前置,这样不至于忙活半天,你跟我说对不起不合适,要杜绝这种骗pao的做法 。
在写多个判断的时候,把不满足可能性高的放在前面 。
在写条件或的时候把为true的放在前面,在写条件与的时候把为false的放在前面 。
另外,如果在循环里调用一个函数,而这个函数里检查某条件,不符合就返回,这种情况,可以考虑把检查放到调用函数的外面,这样不满足的话就不用陷入函数,当然,你也可以说,这样的操作违背软件工程,但看你想要什么,你不总是能够两全其美,对吧?


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

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