170 likes | 319 Views
高性能健壮系统中的内存管理. 合理的内存管理策略带来. 系统性能的提高 更高的运行速度 更小的内存占用 稳定的内存使用量 让系统更健壮 减少因系统设计规模的扩大而带来的负作用 易于调试 减少编码失误率 控制 bug 的坏影响的范围 让系统可以长期不间断的工作. 内存是最难管理的资源. 内存作为一种资源,在应用级和系统底层工作是两种不同的模式。 应用级:我们看到的是连续的虚拟地址空间 系统级:是分块的内存页 内存缺乏原子性、不能用简单的引用记数方式管理。 在传统软件中、内存碎片几乎一定会产生。 从性能角度看,内存并非像程序员们想象的那样有一致性。
E N D
合理的内存管理策略带来 • 系统性能的提高 • 更高的运行速度 • 更小的内存占用 • 稳定的内存使用量 • 让系统更健壮 • 减少因系统设计规模的扩大而带来的负作用 • 易于调试 • 减少编码失误率 • 控制 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 谢谢