`
jishublog
  • 浏览: 873445 次
文章分类
社区版块
存档分类
最新评论

性能——看不到的压力

 
阅读更多

去年过年之前参与了一个项目,对执行项目有了更加深刻的认识,特此记录。

首先项目的功能大致如下:

  1. 系统每天定时从某个外部系统用FTP 的方式获取电话号码相关文件,从周日到周五是增量数据,周六是全量数据。
  2. 系统每天8 点开始处理获取的数据—— 将所有的数据load 到内存中(增量数据大概2万条,全量数据一千两百万左右)
  3. 这个客户本身有自己的用户数据,接近一百五十万条,系统每个小时都需要将所有数据load 到内存中。
  4. 系统为外部系统提供sockethttp 的查询服务。

这个项目实际上是一个已经上线5 年的项目,这次的功能改进是涉及到刚才列出的第一个,这部分最早不是使用文件的方式,而是使用数据库的方式。由于是功能改进,所以这次项目的一个基本原则就是必须延续之前的设计。之前的设计考虑到大数据量loadmemory 里面,并且不能影响用户查询的速度,所以:

  • 所有的数据按照电话号码的前四位,分成100 个组(因为前两位是一样的),每个组叫做一个subCache
  • load 数据的时候,按照号码顺序将所有前缀相同的号码加载到一个新的subCache 中,每当一个subcache 加载结束,与原有的subCache 进行切换,原有的subCache 即可释放。
  • subCache 保存的数据,为了方便查询使用了STL 提供的标准的map

这个项目看起来没有多难,又有之前的代码参考,所以当时安排接手项目的是我们组一个新来没多久的孩子,本科毕业两年多一点,姑且叫他cc 吧。cc 是第一次 做要真正上线的项目,心里很紧张,也自然想借这个项目证明一下自己的能力,一个多月废寝忘食,终于所有功能测试都过了,项目的PM 也很满意,大家很高兴,cc 终于可以轻松一下了!

等到上线的那一天,也是格外的顺利,两台64 位的有8G 内存的机器都上线成功。大家终于松了一口气。 但是,刚刚第三天,噩耗传来,程序使用的内存一直在涨,直到,系统没有内存了,程序挂了。


Faint Faint ,程序挂了!!两台Active/Active 的机器已经挂了一台,另一个的内存使用量眼瞅着冲着7G 就去了,离挂也不远了。天哪, Memory Leak !!!!一定是memory leak !!!!

项目出了这么大的问题,直接惊动了CTO ,立即召开紧急会议,分析原因并安排对策。项目执行过程中,最大的失误就是—— 没有做性能测试!追究完责任,得解 决问题啊,接下来就要开发人员努力去查找root cause ;系统维护人员在生产环境的机器上运行监控脚本,监控机器的内存使用情况,并每个小时定时发邮件给相关人等。


cc 和我开始找原因,我们还尝试寻求几个高手的帮助。刚开始所有人都以为,那么大量的memory leak ,应该很容易就找到,可是事实证明,cc 写的code ,完全查不到有内存泄露的地方。我们做了能够做的所有的code review ,使用了purify 和一些开源的工具,也没有查到任何leak 的地方。

就这样,两个星期过去了,每天每隔一个小时的production 上内存监控的邮件都让我们压力剧增。从内存的增长看起来,只要一有数据load 操作,内存就会涨,每隔三到四天,有一台机器的程序就必定要重新启动。那段时间最期盼的事情就是,有人突然发现出现了问题的代码,然后劈头盖脸的骂过来: 你们! 居然会犯这么弱智的错误!! 系统基本上有三种操作,一种是load 文件中的数据,一种是load 数据库里面的数据,还有,就是查询操作。在我们自己的测试系统中,单独做哪一个操作,系统的内存都会稳定下来,但是,只要三种操作掺杂在一起,内存就out of control.

找不到内存泄露的地方,就只能推测(说不好听点,就是用猜的),最后能够想到问题就是STLmap 没有及时的把memory 还给操作系统。可是,可是,全世界有无数的程序使用STLMAP ,为什么别人的程序没有碰到这种问题?!!


眼看着就山穷水尽了,执着于当下是不够的,不能找到root cause ,那么必须有替代方案,否则,每三天重启一下机器,客户也不能答应啊!经过讨论,选了两条路:

  1. memory pool 的方式,在map 里面保存指针,new 出来的对象都从memory pool 里面获取,这样至少可以控制住new 出来对象的内存;
  2. 使用opensourcememory db

但是阅读了一下memory DB 的代码,发现这么做程序代码改动太大了,因为已经上线的系统,原则只有一个——尽量少的改动。所以实际上只剩一种选择—— memory pool

既然决定了,那么就开始动手修改吧。cc 开始添加memory pool ,另外还多加了一个修改,因为map 里面的key 使用的电话号码,之前用的是string 类型,为了节省内存,加上电话号码的特殊性,全部改成 long 型。写代码的过程中,memory pool 使用了STL list 。改动做完,在测试环境程序依然会从刚启动的2.1G ,攀升到最高的6.8G6.8G 啊,按照以前的经验,性能一旦开始出问题,就可能急剧恶化,完全失去控制。这时一个比较有经验的同事建议在memory pool 里面使用STL deque 。就这一个改动,程序终于可以运行在6G 以下了!!!神奇啊,STL 真是博大精深。


cc 改完,做了两轮完整的功能测试,以及长达7 天的性能测试之后,终于在过年之前上线了。到目前为止,运行良好。


就在cc 代码改进的过程中,我们竟然又有想到可以改进的空间。其实现在想来倒也不难,既然我们认为可能是map 的内存回收出现问题,那么有两种选择,第一,不用map ;第二,改进map 的回收算法。所以,就有了下面两种方法。

  1. 使 用map 是为了查找的时候更快。那么有什么可以替换的方式呢?在我们这个应用中,有一个比较特别的点,就是电话号码可以用long 型表示,那么,可以选择 使用一维数组的方式来替换map ,而电话号码的后半部分(除去前四位)可以作为数组的下标。按照号码的长度就能够计算出来每次new subCache 的时候会用到的内存,并且可以自己控制释放。(^_^ ,说说到这个想法,居然是有一天在我下班回家的路上,突然蹦到我的脑袋里面的,我还是有点小得意的。)
  2. 改进map 的回收算法。这个是cc 研究侯捷的《STL 源码剖析》之后找到的想法。既然目前使用起来的对我们的应用而言,看起来不够合理,那么可以重写之。

新的版本上线之后,cc 也根据上面的两种方法修改了程序,事实证明这两种方式下,内存是可以稳定的。虽然这两个版本可能永远不会上线,但是在这个过程中,我们的思维得到了极大的开拓,心理承受能力也飞速增长。


事实再一次证明,所有会上线,并且需要7*24 小时运行的程序,就没有简单的,功能之外,性能是非常重要的。为了这个项目真是,衣带渐宽终不悔,为伊消得人憔悴哇。


分享到:
评论

相关推荐

    性能测试进阶指南——LoadRunner11实战 part2

    《测试实践丛书:性能测试进阶指南·LoadRunner 11实战》是一本基于HP LoadRunner 11工具的指导用书,从性能测试原理到工具使用再到项目实施,全面介绍了性能测试的各个方面,其内容基本主线说明如下。 第一步...

    性能测试进阶指南——LoadRunner11实战 part1

    《测试实践丛书:性能测试进阶指南·LoadRunner 11实战》是一本基于HP LoadRunner 11工具的指导用书,从性能测试原理到工具使用再到项目实施,全面介绍了性能测试的各个方面,其内容基本主线说明如下。 第一步...

    性能测试进阶指南——LoadRunner11实战 part3

    《测试实践丛书:性能测试进阶指南·LoadRunner 11实战》是一本基于HP LoadRunner 11工具的指导用书,从性能测试原理到工具使用再到项目实施,全面介绍了性能测试的各个方面,其内容基本主线说明如下。 第一步...

    性能测试进阶指南——LoadRunner11实战_(完整)扫描版_@vs.part1

    《测试实践丛书:性能测试进阶指南·LoadRunner 11实战》是一本基于HP LoadRunner 11工具的指导用书,从性能测试原理到工具使用再到项目实施,全面介绍了性能测试的各个方面,其内容基本主线说明如下。 第一步...

    性能测试进阶指南——LoadRunner11实战_(完整)扫描版_@vs.part2

    《测试实践丛书:性能测试进阶指南·LoadRunner 11实战》是一本基于HP LoadRunner 11工具的指导用书,从性能测试原理到工具使用再到项目实施,全面介绍了性能测试的各个方面,其内容基本主线说明如下。 第一步...

    性能测试进阶指南——LoadRunner11实战_(完整)扫描版_@vs.part5

    《测试实践丛书:性能测试进阶指南·LoadRunner 11实战》是一本基于HP LoadRunner 11工具的指导用书,从性能测试原理到工具使用再到项目实施,全面介绍了性能测试的各个方面,其内容基本主线说明如下。 第一步...

    性能测试进阶指南——LoadRunner11实战_(完整)扫描版_@vs.part4

    《测试实践丛书:性能测试进阶指南·LoadRunner 11实战》是一本基于HP LoadRunner 11工具的指导用书,从性能测试原理到工具使用再到项目实施,全面介绍了性能测试的各个方面,其内容基本主线说明如下。 第一步...

    性能测试进阶指南——LoadRunner11实战_(完整)扫描版_@vs.part6

    《测试实践丛书:性能测试进阶指南·LoadRunner 11实战》是一本基于HP LoadRunner 11工具的指导用书,从性能测试原理到工具使用再到项目实施,全面介绍了性能测试的各个方面,其内容基本主线说明如下。 第一步...

    性能测试进阶指南——LoadRunner11实战_(完整)扫描版_@vs.part3

    《测试实践丛书:性能测试进阶指南·LoadRunner 11实战》是一本基于HP LoadRunner 11工具的指导用书,从性能测试原理到工具使用再到项目实施,全面介绍了性能测试的各个方面,其内容基本主线说明如下。 第一步...

    搭建高可用mongodb集群(二)——副本集

    在上一篇文章《搭建高可用...但是光通过主从模式的架构远远达不到上面几点,由此MongoDB设计了副本集和分片的功能。这篇文章主要介绍副本集:mongoDB官方已经不建议使用主从模式了,替代方案是采用副本集的模式,

    淘宝技术这十年

    在技术架构的制约下,团队协作越来越艰难,代码越来越臃肿,开发的效率越来越低,新业务的需求越来越多,老业务的压力眼看就要超过系统的容量了。这时候,架构该做怎样的调整?又一次的脱胎换骨,欲火重生。重生后,...

    计算机应用专业调研报告(1).doc

    我们再来看,专业人才招聘网站——中华英才网发布了最新一期的IT职场人气排行榜。 发布职位数量的行业排名大多仍沿袭上月的顺序,计软、互联网、IT服务保持前三甲不 变,咨询、财会、法律各种专业服务行业紧随其后...

    计算机应用专业调研报告(3).doc

    我们再来看,专业人才招聘网站——中华英才网发布了最新一期的IT职场人气排行榜。 发布职位数量的行业排名大多仍沿袭上月的顺序,计软、互联网、IT服务保持前三甲不 变,咨询、财会、法律各种专业服务行业紧随其后...

    数据仓库的概念及特点

    于是,有人感叹:20年前查询不到数据是因为数据太少了,而今天查询不到数据是因为数据太多了。针对这一问题,人们专门为业务的统计分析建立一个数据中心,它的数据可以从联机的事务处理系统、异构的外部数据源、脱机...

    KesionCMS v9.5.140605 免费正式版本(utf-8).rar

    长期积累,网站中可能存在大量的无用标签,每次读出标签时对系统的性能或多或少哦都会有所影响,至此,新版本增加一键清理无用标签功能,标签管理开发为列表形式,更近一步兼容多种浏览器。 后台稿件统计增设可按...

    KesionCMS v9.5.140605 免费正式版(gbk).rar

    长期积累,网站中可能存在大量的无用标签,每次读出标签时对系统的性能或多或少哦都会有所影响,至此,新版本增加一键清理无用标签功能,标签管理开发为列表形式,更近一步兼容多种浏览器。 后台稿件统计增设可按...

    什么是VLAN

    另外,来自市场的压力使各大网络厂商立刻将新标准融合到他们各自的产品中。  802.1q帧格式:  · Cisco ISL 标签  ISL(Inter-Switch Link)是Cisco公司的专有封装方式,因此只能在Cisco的设备上支持。ISL是一...

Global site tag (gtag.js) - Google Analytics