1 / 53

游戏的优化

游戏的优化. 不仅仅是帧速率. 我们将谈论什么 ?. 何时何地需要做优化 ? C 和 C++ 的比较 C++ 中的性能问题 算法优先 我们需要 C++ 的高级特性吗?. 优化无处不在. 最好的优化器是你的大脑,而不是编译器 评测而不是臆测 Windows 游戏不应该有特权 Windows 游戏首先是一个 Windows 程序 每一点资源的节省都将是有意义的 专家的选择是不优化. FPS?. 提高了 10 fps 表示什么含义? 10fps->20fps 100fps->120fps 最高帧速率和平均帧速率 Loading 时间

airlia
Download Presentation

游戏的优化

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 游戏的优化 不仅仅是帧速率

  2. 我们将谈论什么? • 何时何地需要做优化? • C 和 C++ 的比较 • C++中的性能问题 • 算法优先 • 我们需要 C++ 的高级特性吗?

  3. 优化无处不在 • 最好的优化器是你的大脑,而不是编译器 • 评测而不是臆测 • Windows 游戏不应该有特权 • Windows 游戏首先是一个 Windows 程序 • 每一点资源的节省都将是有意义的 • 专家的选择是不优化

  4. FPS? • 提高了 10 fps 表示什么含义? • 10fps->20fps 100fps->120fps • 最高帧速率和平均帧速率 • Loading 时间 • 关心一下 CPU 占用率 • 了解 Windows 多一点

  5. 记时器 • TimeGetTime • QueryPerformanceCounter • RDTSC • 精度 • 多任务环境的影响 • 流水线 • 测不准原则

  6. 微观和宏观 • 微观上的优化 • CPU指令、流水线吞吐量、等待时间 • 有限的硬件优化 • 有限的编译器优化 • 宏观上的优化 • 算法和代码结构的改进 • 减少需要处理的数据量,减少处理的频率和次数

  7. C 与 C++ 微观上的比较 • C 比 C++ 快 10%? • 不要迷信书本 • 证据? • C++ 编译器的改进 • 更合理的参数传递方式 • Inline • 堆栈和函数调用 • 静态变量的使用

  8. C++提供更强的语言特性 • new/delete malloc/free • C++ exception setjmp/longjmp • 虚函数 函数指针数组 • Template 宏 • 标准库

  9. C 的优势 • 简单 • 可移植性更强 • 接口简洁 • 更少的二义性 • CRT 开销小 • 编译速度快

  10. C++ 需要了解更多

  11. STL • 最被人喜爱的容器 • std::map • std::string • std::vector • std::list • 大多数情况他们没有被正确的使用

  12. std::map • 插入是很慢的 O(log(N)) • 有额外的内存消耗 (三个指针+颜色) • 大多数情况,我们需要的只是查找 • 数组+二分查找 • Hash map 通常可以提高效率,但不绝对 • 还有更多的优化手段 • lua 的实现 • 大话西游的实现

  13. std::string • 还有一种字符串叫作 const char * • const std::string & • 不要依赖 COW (copy-on-write) • 考虑多线程环境 • 良好的设计下,cow 通常多余 • Lua 如何处理字符串?

  14. std::vector • std::vector 并不仅仅是数组 • 通常我们把 vector 作为数组使用 • Vector::push_back() 常引起内存重分配 • vector::reserve() • vector::clear() 不一定释放内存 • POD 类型的优化 • 记住:从 C 语言开始,就支持了数组

  15. std::list • std::list 是一个双向链表 • std::list 有内存的额外开销 • 链表可以在常数时间插入,而当 N 不大的时候,优势并不明显。

  16. 正确的使用STL • STL 是 C++ 提供的强有力的工具 • STL 的使用都是有开销的 • STL 并不能解决我们所有的问题 • 有些问题可以用 STL ,但那并不是最好的解决方案 • 让代码达到最佳的性能,需要用我们的大脑

  17. 重新发明轮子? • 不要因为你能够做到而重新实现 STL • 几乎所有的 MyVector MyString MyMap 都不如 std::vector std::string std::map • 更多的了解 STL 更多的了解 C++

  18. CRT 的使用 • sprintf(s,”%d”,n); • 为什么不用 itoa ? • sprintf(s,””); • 为什么不用 s[0]=‘\0’; • printf 与 puts • 不要忽略 CRT 的开销

  19. 重写 CRT? • 优化 memcpy:MMX 版本、SSE 版本… • 任何小于 64k 数据复制的优化都没有意义 • 重写 string 库,MyStrlen MyStrcmp … • CRT 可以做的更好 • Intrinsic 函数 • #pragma intrinsic()

  20. 内存优化 • 展开循环,消除数据相关性 • 数据并行处理 • 减少数据结构的尺寸,让数据尽量紧凑的放在一起 • 数据对齐 • 了解内存的工作方式

  21. 内存管理优化 • C++ 提供了更灵活的内存管理机制 • new/delete 不一定是最好的方式(STL就不用) • 自定义内存分配器 • 方便调试 • 分配速度和内存碎片同样重要 • 注意分离模块的问题 • DLL 最容易出错

  22. 算法 • C++ 更适合实现更复杂的游戏引擎 • 引擎的复杂度提升,层次的增加,会降低效率 • 更高的复杂度是为了宏观上的优化

  23. 脏矩形

  24. 问题 • 脏矩形的合并算法并不简单 • 合并后的脏区域并不是一个矩形,不方便做图片裁减 • 有许多的物体在屏幕上移动 • 卷动屏幕 • 图像引擎设计的复杂度

  25. 改进的脏矩形 • 分格处理 • 渲染管道 • 绘图操作对象化

  26. 滚动优化 • 更大的back buffer • 破碎的分格

  27. 覆盖优化

  28. C++的高级特性 天使还是恶魔?

  29. Template 避免重复的代码 void _blit(pixel *dst,const pixel *src,size_t s,bool mask_blit) { for (size_t i=s;i!=0;--i,++dst,++src) { if (!mask_blit || *src!=mask_color) *dst=*src; } } template <bool mask_blit> void _blit(pixel *dst,const pixel *src,size_t s) { for (size_t i=s;i!=0;--i,++dst,++src) { if (!mask_blit || *src!=mask_color) *dst=*src; } }

  30. void blit(pixel *dst,const pixel *src,size_t s) { _blit<false>(dst,src,s); } void mask_blit(pixel *dst,const pixel *src,size_t s) { _blit<true>(dst,src,s); }

  31. 矩阵运算 • Matrix A,B,C; • A=B+C; • Matrix operator+(const Matrix &lhs,const Matrix &rhs); • Matrix & my_type::operator=(const Matrix &v); • 如何避免临时对象的返回? • 转化为 A=B; A+=C;

  32. Expression Templates template<typename T> class add_type { const T& _lhs; const T& _rhs; public: add_type(const T &lhs,const T &rhs) :_lhs(lhs),_rhs(rhs) {} T& calculate(T &result) const { result=_lhs; result+=_rhs; return result; } }; template <typename T> add_type<T> operator+(const T &a,const T &b) { return add_type<T>(a,b); }

  33. class Matrix { /* ... */ Matrix& operator+=(const Matrix &v); Matrix& operator=(const add_type<Matrix> &v) { return v.calculate(*this); } /* ... */ }

  34. 编译时计算 template<int N> class factorial { public: enum { value = N * factorial<N-1>::value }; }; template<> class factorial<1> { public: enum { value = 1 }; };

  35. 冒泡排序 inline void compare_swap(int &a,int &b) { if (a>b) { int t=a; a=b; b=t; } } void sort(int *data,int n) { for (int i=0;i<n-1;i++) { for (int j=i+1;j<n;j++) { compare_swap(data[i],data[j]); } } }

  36. template<int N> struct inner_loop { static inline void expand(int* data) { compare_swap(*data, data[N]); inner_loop<N-1>::expand(data); } }; template<> struct inner_loop<0> { static inline void expand(int*) {} }; template<int N> struct sort { static inline void expand(int* data) { inner_loop<N-1>::expand(data); sort<N-1>::expand(++data); } }; template<> struct sort<1> { static inline void expand(int* data) {} };

  37. int main() { int a[]={3,2,1}; const int len=sizeof(a)/sizeof(a[0]); sort<len>::expand(a); for (int i=0;i<len;i++) { printf("%d,",a[i]); } } // sort<len>::expand(a) 展开后的代码 compare_swap(*data,data[2]); compare_swap(*data,data[1]); ++data; compare_swap(*data,data[1]);

More Related