You are on page 1of 17

高性能健壮系统中的内存管理

合理的内存管理策略带来
• 系统性能的提高
– 更高的运行速度
– 更小的内存占用
– 稳定的内存使用量
• 让系统更健壮
– 减少因系统设计规模的扩大而带来的负作用
– 易于调试
– 减少编码失误率
– 控制 bug 的坏影响的范围
– 让系统可以长期不间断的工作
内存是最难管理的资源
• 内存作为一种资源,在应用级和系统底层工作是
两种不同的模式。
– 应用级:我们看到的是连续的虚拟地址空间
– 系统级:是分块的内存页
• 内存缺乏原子性、不能用简单的引用记数方式管
理。
– 在传统软件中、内存碎片几乎一定会产生。
• 从性能角度看,内存并非像程序员们想象的那样
有一致性。
– 性能敏感的软件或实时系统,内存管理有更苛刻的要
求。
性能
• 无论语言多高级,在你使用的语言层面总
有事情可以做。
• 编译器并非万能
• 人有机会比优化器做的更好
深入 RAM 硬件底层
• 抽象与细节的矛盾
– 抽象是为了设计更大的系统
– 细节是为了更高性能的工作
• CRT→OS→ 虚拟内存地址→物理内存地址
→ BIOS → Cache→ 储存控制芯片→ DRAM
• DRAM 是晶体管和电容构成的二维电路
• Cache 使用 SRAM ,可以工作在更高频率下
• 控制芯片以串行模式工作
• RAM 性能的提高并非无差别的
结论?
• 没有永远不变的原则
– 大原则变化的慢
– 没有一劳永逸的解决方案
• 内存访问很廉价但有代价
– 减少内存访问的次数是很有意义的
• 随机访问内存慢于顺序访问内存
– 请让数据物理上连续
• 集中内存访问优于分散访问
– 尽可能的将数据紧密的存放在一起
• 无关性内存访问优于相关性内存访问
– 请考虑并行的可能性、即使你的程序本身没有使用并行机制
• 控制周期性密集访问的数据大小
– 必要时采用时间换空间的方法
• 读内存快于写内存
• 代码也会占用内存,所以、保持代码的简洁
关于优化的参考
• X86 平台, Agner Fog 是绝对的权威。
– 《如何优化 Pentium 微处理器》
• 《代码优化:有效使用内存》
• 《深入理 解计算机系 统 》
制定合理的内存管理策略
• 了解你的系统如何使用内存
– 系统中各种对象有怎样的生命期?
– 峰值时系统需要多少内存?这个值因何而变?
– 系统稳定工作的时候,需要多少内存?那些对
象需要?哪些内存需求是稳定不变的,哪些是
动态增减的?
• 手工管理内存和自动管理内存 (gc) 都不是
万能的。
– 适当的时候引入 gc 或近似的机制
不变的内存需求
• 各施其责、让操作系统帮助你更好的解决问题
– 只申请不(主动)释放并非坏习惯
– 内存块不是原子对象,即使你还给了系统,系统也未
必可以利用它们
– Bug 经常出在程序退出时,可用户在意它们吗?你真
的需要在意吗?
– C++ 带来的错觉:令人困扰的单件生命期问题。
• 模块化设计的问题
– 动态链接库和独立进程服务
生命期可预期的内存需求
• 内存块的生命期决定于一个特定对象或一个特定
事件
– Web server 中、大部分对象跟连接相关
– Game server 中、大部分对象跟独立玩家相关
– 3d engine 中、大部分对象跟 3d 实体相关
– ……
• 偶尔、复制好过引用
• 成批的分层次回收内存有利于减少内存碎片
• 把相关的数据结构尽可能的物理上保持连续
• 不同层次的对象引用的内存在设计上分离
可再生的内存数据
• 3d engine 中的资源管理
– 一切内部资源加载后不再删除其资源 handle
– 任何资源皆可再生(往往指从外存重新加载)
– 资源占用的内存的回收和再利用和逻辑层无关
– 资源的预读及并行化处理流程于主逻辑正交设

– 显存对象是不同类型的内存数据、应独立管理
临时内存
• 程序运行栈
• 用堆模拟一个栈
• 关于 C++ 的 auto_ptr
• 关于 C++ 的容器: vector list map ……
• 异常的处理:
– C++ 异常
– longjmp
String 的管理
• String 类有多重要?
– std::string ? CString ? boost::rope ?
– Copy on Write 是天使还是恶魔?
– 为什么不用 const char * ?
• 通常,我们只需要 raw pointer
• const char * 往往只是一个 handle ,一个可以
比较和排序的 handle
• 忘了宽字节吧, UTF-8 可以解决大部分问题
• 没有完美的 string 类,如果你认为你设计出了
一个,那么你一定忘掉了要用它做什么。
垃圾收集 (GC)
• C/C++ 需要 GC 吗?
• 自动化内存管理无处不在。
– 手工写出了每一个 new/delete malloc/free 并不意味
着你在手工管理
– 引用计数同样是一种自动化管理
• GUI 、 3d 场景管理不可能离开自动化内存管理
• Mark-sweep GC 的优势
– 使用 gc 并不意味着偷懒,通常是因为良好的设计的
需要
– gc 不等于低效、间隙停顿、高内存占用
– 请控制 gc 的粒度
– http://code.google.com/p/manualgc/
自定义内存管理器
• 更好的控制内存碎片
• 更好的监控内存使用
• 监视悬空指针和内存访问越界
• 易于调试
– 寻找内存泄露
Q&A

谢谢
http://blog.codingnow.com

You might also like