paladin career
博客:http://blog.sina.com.cn/auroratony

  十三年前第一次听Bob Dylan的那首“blowing in the wind”。很多年前我开始想,一个程序员写多少代码才算入门呢?对写程序的认识从能实现功能就万事大吉到有意识的注重代码质量和效率的转变点应该算是入门阶段的一个里程碑吧。每当我遇到一个无法逾越的技术点,或是自认为刚刚学会的一个小手段能解决一问题时,其实都是遇到了知识断层的障碍。不知不觉弥补了断层过后就会恍然大悟:原来那个问题要那样去解,而我当时的小聪明着实不高明啊。程序员对代码优化的认知也是阶段性的,优化的能力应是随着无法解释的抽象层面的减少而成长的。
 
  看一些人写技术博客在措辞上过于谦虚了,这可能也是被不看文章瞎评论的人惹怕了吧。好在我脸皮厚,写博客只注重清晰表达自己。写字直白和为人不够谦逊在我眼里向来没有联系。我和大部分有兴趣仔细看这篇文章的人没多大差别,只是一个写了几年代码的游戏程序员。这里只写我对游戏程序效率优化的一点想法。
 
 
抠不如抓
 
  茴香豆中hui有多少种写法?不用循环和分支语句怎么实现两数交换?STL迭代器移动++写在前头好还是后头好?循环中的特定代码需要外提吗?按我对编译器的认识,现代C/C++编译器都有足够强的能力推导出代码中能够优化掉的此种程度的时间复杂度细节。一些琐碎的东西很可能我们想到一个优化方案,但是实现之后发现效率反而不如从前了。代码和流程足够简洁,即使在效率测试中真的发现某一块是性能瓶颈再去优化也很容易。步步惊心的去抠细节效率不如阶段性的做了足够准确的profile后大把抓大块的瓶颈。但是代码质量与效率是有区别的,该用引用或指针就不用对象,该加const就加(我就先不吐槽恶心的C++ const了),避免临时对象的创建,避免不必要的拷贝……这类有助于提高代码质量的细节不仅牵涉效率问题,对程序的稳定和健康都是有益的。过早优化是泥沼,放任滥写细节和过晚优化同样是泥沼。不以善小而不为,不以恶小而为之。
 
 
无差别心
 
  如果你在一个网络游戏团队工作,人家把你安排到了客户端或服务端之后你也把自己职业生涯的活动范围限定死在上述两个方面中的一个吗。游戏程序即使有明显的层次划分也应该是贯通一体的,网络通信把网络游戏从进程上分隔开了,可千万别认为物理上的隔阂在逻辑上也是楚河汉界一样,纯粹转发性质的模块做得越透明越好。如果非要做个划分我宁愿按engine、gameplay的方式分,前者包括渲染、物理、数据持久化等工程的基础设施,后者调用前者,包括逻辑对象、对象间交互手段等。游戏程序的效率考量不外乎下面几个方面:

1. CPU占用;
2. RAM占用;
3. 外存-RAM传输;
4. GPU占用;
5. GRAM占用;
6. RAM-GRAM传输;
7. IO。

  把这七点罗列出来对于这篇备忘来说还是很有必要的。从这些角度出发去考量程序的效率应该成为游戏程序员的本能,在遇到低下的效率时多针对不同方面做下profile,然后制定具体的优化办法,效果不明显就试试不同的角度。我曾犯过显存带宽、硬盘带宽、缓存填充率上不去却在方面瞎折腾的毛病,结果当然是起不到作用的。找瓶颈往往比想对策更难,因为前者更依赖经验来快速判断,具体问题总是要具体分析。找准了症结后相应的改进对策就容易得到,即使自己没有这方面的经验,从网络、团队其他成员那总能得到些启发,你遇到的问题,多半别人早就遇到过且有现成的成熟解决方案(没有的话那就是一个非常值得造的轮子了)。对于时间瓶颈,一般是针对密集计算或海量信息处理。在大局上提高并发程度(可惜人脑更擅长串行化的流程,不展开说了,推荐看以前在《多线程程序设计中的8条简单规则》提到过的《并发的艺术》);在细节上可针对具体体系结构做有针对性的优化,而且随指令集、片内缓存、编译器推导能力手段力度也不一样,对于海量运算,这种抠出来的性能还是值得去优化的。另外可能经常被错误定位或忽视的是访存开销和IO开销,适当迭代调整和测试数据块访问的粒度可以达到总线的充分利用,很多存储器在硬件读写上是并行不了的,我想XBox360这种游戏主机的SDK中附带的调整文件在光盘介质中的物理布局的工具的作用就是让光盘的寻道、读取、缓冲、传输等操作间能达到平衡吧;另外使用缓存以空间换时间能缓解很多不同存储器之间数据传输的开销,但毕竟这是一种有代价的置换策略,不能一味的把大堆东西都堆砌到缓存上,优化的一个原则是好钢用在刀刃上。
锐亚教育

锐亚教育,游戏开发论坛|游戏制作人|游戏策划|游戏开发|独立游戏|游戏产业|游戏研发|游戏运营| unity|unity3d|unity3d官网|unity3d 教程|金融帝国3|8k8k8k|mcafee8.5i|游戏蛮牛|蛮牛 unity|蛮牛