qyb的博客
python 性能调优一则
最近几天新写的一个日志处理程序深受性能不足所困扰(每5分钟处理一次httpd日志,统计用户的连续访问和停留时间)。显然每5分钟处理过的数据必须至少保留 30 分钟后才能销毁,否则所谓连续访问无从算起。
问题是第一次处理的时候,程序很快就结束了,大概30秒;但第二次时间就增加到60秒左右,第三次时间增加到90秒上下...
很容易想到这是由于数据没有释放,导致在做查找操作的时候时间也随之延长...但我这里明明用的是 dict,应该是 o(1) 的复杂度,为什么这里表现出了线性增长关系呢??
代码很简单,我检查了又检查,函数封装了一个又一个(为了便于profile),从 hotshot 换到 cProfile,就是找不出程序慢在何处。
从 profile 结果看,最让人惊讶的就是主函数所调用的各个子函数的用时之和远远小于主函数所消耗时间(主函数内的计算量可以忽略不计),比如这样:
ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 180.979 180.979:1( ) 1 114.522 114.522 180.979 180.979 test.py:33(main) 5521410 32.147 0.000 32.147 0.000 {method 'split' of 'str' objects} 5521409 16.107 0.000 24.152 0.000 test.py:7(process) 11042818 6.586 0.000 6.586 0.000 {method 'has_key' of 'dict' objects} 5521413 4.577 0.000 4.577 0.000 {method 'readline' of 'file' objects} 3 3.594 1.198 3.602 1.201 test.py:20(commit) 5521409 1.979 0.000 1.979 0.000 {method 'strip' of 'str' objects} 3854644 1.459 0.000 1.459 0.000 {method 'append' of 'list' objects} 3 0.000 0.000 0.008 0.003 {time.strptime} 1 0.001 0.001 0.006 0.006 /usr/local/lib/python2.5/_strptime.py:12( ) 10 0.000 0.000 0.004 0.000 /usr/local/lib/python2.5/re.py:186(compile)
总共 180 秒执行时间,但其它所有函数加起来也不超过 80 秒,另外的那 100 秒去哪里了呢?
然后就去翻 python 手册的 profile 部分,在看 timeit 的时候无意中扫过这么一段:
Note: By default, timeit() temporarily turns off garbage collection during the timing. The advantage of this approach is that it makes independent timings more comparable. This disadvantage is that GC may be an important component of the performance of the function being measured. If so, GC can be re-enabled as the first statement in the setup string.
我突然福至心灵,在代码里面禁止了自动垃圾收集,然后去测试,哈,问题立刻解决。不仅仅是丢掉的 100 秒找回来了,所有的操作速度都大大提高。原来分析5分钟数据要30秒的,现在10秒就搞定了!
这下就明白刚才的问题出在哪里了——在日志分析过程中创建出了大量的对象,而这些对象还都不能销毁,等待以后使用,结果就导致 python 频繁的 gc(陈儒的《Python源码剖析》里介绍是缺省每创建700个对象就执行一次 gc),而gc遍历队列是在线性增长的,这就表现为大量的时间被消耗掉,而且执行时间越来越长。
以前从来没有深入了解过 java,今天是第一次感受 gc 的作用 :PP
附:感觉还是 cProfile 比 hotshot 好,用 hotshot 很多系统内置函数的执行时间(比如字典的has_key, 字符串的 split)是看不到的。
实践证明,水杯是笔记本第一大杀手
上一次笔记本损坏是5年多前了,那时候还是租房住,给宝宝洗澡的时候把水弄到键盘上了,好像就此彻底挂掉。
周六,不小心把水泼在了俺的 vostro 1000 上。立刻关机。等它干了以后,能正常启动,就是键盘上有若干键不能使用。
首先尝试自己动手,拆下键盘,把出问题的几个键都拔下来,拿着电吹风吹啊吹(这里要附带说一下,它的键盘是防水设计——就是把水尽量积在键盘上,而不是往主板上流;这样的设计还是很科学的),吹完以后问题照旧。
于是拿起电话打400,人家周末只有电话应答。只好周一再打电话,就说是键盘坏了,支持工程师问了问安全模式和BIOS设置模式下键盘是否仍然有同样问题,然后就决定给我换键盘。
很快今天上来工程师过来,把键盘换了,然后说12层还有另一个搜狐的员工笔记本报修就上楼了——汗...
这半年 vostro 1000 用下来,觉得还成。足够稳定,Vista 也运行挺好。除了硬盘温度比较高,让人怀疑如果在炎热的湖北使用它,就要天天开空调了
上一台 Thinkpad R51e 已经安然用了2年多,实践证明大厂出的廉价机种还是很可靠的,现在希望这台 DELL 也能坚持 3-4 年的寿命。
关于电子邮件
- 思科收购 PostPath。这是 Yahoo 收购 oddpost、zimbra 后,我所听说的电子邮件领域又一个重量级的收购(貌似 google 和 ms 也偷偷摸摸的收购不少和邮件相关的厂商)。更重要的是,收购方并不是一个传统意义上的软件/服务提供商。
- 最近装了 xobni,一个 outlook 插件。它带给我自 Gmail、plaxo 后,第三次的惊喜——原来邮件还可以发掘这样的应用!另外,如果哪一天有第三方能为 webmail 开发出类似重量级的插件应用,才能表明 webmail 是可以代替客户端的,以这个标准衡量,我们要走的路还很长。
- 今天参加了一个 epsilon 赞助的会议。本来不太清楚他们,但从这次的情况看,还是一个挺靠谱的公司,不晓得中国地区的业务能运营的怎么样。如果想做电子邮件直销的话,可以和他们合作试试。
- 直到现在,和世界上任何一个人通信,电子邮件仍然是最快速、简易、廉价的解决方案。IM 何时才能做到这一点?我觉得要等到 EMAIL+XMPP 来引爆。
最后,当初几个一起做邮件的同事都不再和邮件有关系了,9年后只剩我还停在这个"板块"... :(
不过从增长潜力看,我觉得这个板块蛮有前途的。:)
走过渐渐熟悉的街头,十年之后。。。
聚会时间:中秋节假期(9.13-9.15,根据国家规定调整)地点:天津
日程安排:第一天中午1:00报道,之前来的同学自由活动(打牌、聊天叙旧)。
下午1:00 - 2:00,简单午餐。
下午2:00 - 4:00 友谊赛(足球、篮球)
晚上6:00- 晚餐(喝酒)
第二天:上午9:30 -12:00 与老师座谈
致母校及同学词(选出代表)
给母校、老师送纪念品(给每位老师礼物的价位:300左右 )
请院长及班主任老师讲话
各班代表发言,介绍班上同学大概的10年经历
根据时间安排,自由发言
最后大合唱:南开校歌
中午 12:00- 2:00 与老师一起午餐
下午 2:00 - 3:30 游南开
下午 3:30 - 6:00 小班聚会
老师讲话
自由发言,介绍10年经历
合唱:南开校歌
晚上 6:00- 12:00 晚餐 + 娱乐(卡拉ok、打牌、麻将等)
第三天:返程
准备工作:
1、收集签名定做10周年t恤2、统计通信地址及联系电话,落实是否参加、并汇总制作通信录
3、确定老师参加人数、会场及食宿安排
4、外地同学需预定返程车票
5、给母校及老师的礼物
6、致母校及同学词
7、各班代表的发言
8、联系摄像的准备工作,后期摄像、照相、光盘编辑制作
9、设立账户,参加的同学开始汇款
费用:1、路费自理
2、礼品费用
3、餐费
4、其他娱乐费用
5、t恤制作费用
6、摄像费用,后期制作费用
预算:在聚会人数超过40人情况下,按人均400元以上预算。
Gears 0.4!!
自从 gears 0.3 发布的时候宣称下一版本将会有 Blob() 支持的时候,我就在一直等着 0.4 的到来,还为此特意加入了它的 google group。
现在,无需自己编写浏览器插件,就可以利用 gears 方便的实现 web 的文件断点上传了(我今天已经写了一个小例子验证)。甚至 gears 还拟定了一个 ResumableHttp Upload 的协议规范
如果没有许可协议的限制,以后我们就会鼓励用户下载 gears 来上传大附件了。
现在发现 Gears 的目标是给浏览器打 patch,让老古董们能跟得上 HTML5 的进展。以前觉得它只是一个 offline 应用的框架,理解还是狭隘了。
现在实施的技术交流会
小熊留言问到 screen 是不是窦窦同学的报告,这里说一下我们现在的技术交流会形式:
定期指定一个技术课题交给某人做研究,大概三周后把其研究结果给所有技术人员做报告。
1. 这个技术课题是未来工作中可能会应用,但现在大部分同事还没有接触过的领域
2. 该流程的目的是开拓大家的技术知识面,所以研究工作会交给本来对该方面不太熟悉的人进行——虽然 screen 这个软件窦窦很早以前就用过,但这个做报告的同学是对 screen 一无所知的
3. 该流程的另外一个目的是给每个人上台做演示的机会。增强各个小组之间的交流
4. 三周时间准备是不是有些太短?从研究的角度来看,是有点短;但另一方面这样每个季度也就不过4次集体交流,我觉得周期不能再长了。所以我们不会选太高深的课题。另外,该研究完全可以在上班时间来进行,这是工作任务的一部分。
4. 三周时间是不是有些长?因为在第二周会首先试讲一下,听众是他的leader和我。我们会指出一些问题,帮助他下一次能在众人面前做更好的表演
5. 技术课题是谁提出的?现在还是由我来提出,希望以后这个事情可以交由邮件中心技术委员会来讨论决定。
6. 该活动我们已经进行了两次。第一次是 mysql-proxy,第二次是 screen,下一次是 javascript 混淆工具
7. 上面提到的"邮件中心技术委员会"是个什么机构?我们是一个很官僚的部门,因此成立这个委员会展示我们的行政作风。
hehe,大型 E-Mail 系统是一个涉及面很广的项目,在 N 个方面都需要有技术专家来支撑,需要有一个核心团队来推动提升部门的技术能力
深入浅出 screen
这周的内部技术交流会,是一个同事介绍 screen 的使用。俺一时嘴痒,就从怀旧开始,给大家从终端开始发散:
十年前,刚接触 UNIX 主机的时候,机房里的终端已经基本不再使用了。但调试维护路由器交换机总偶尔会碰上忘带串口线或者针头不匹配,前辈就从一堆老终端里翻出台合用的代替。第一次看见别人用终端印象非常深刻——总算知道windows那个“超级终端”,或者 telnet.exe 里的 vt100 对应的实物是什么了。
从形态上,terminal 和 console 是一致的,就是输入设备和输出设备的组合。它自己没有计算能力,任务在主机上执行。
在终端键盘上敲一个字符,比如 'a',首先把 'a' 送到主机上,主机再把这个 'a' 回显(echo),然后我们才能在终端屏幕上看到这个 'a'。和在编辑器里输入并看到一个 'a' 相比,是完全不一样的概念。
最近几年入行的新人是不太可能有机会亲手摸一下终端了(可在 google 上图片搜索 vt100 或 vt220 过过眼瘾)。但如果安装过 Linux 操作系统,它的文本控制台(console)可以很好的帮助理解 screen。
A. Linux 控制台,缺省有 6 个虚拟终端,我们可用 Alt-F1/F6 来依次切换;在 screen 里就可以这么干。
B. Linux 控制台的某虚拟终端上,登录进去,然后拔掉键盘,拔掉显示器,再把它们插上,你会发现刚才登录的状态还保持在;screen 也是这样的——在不可靠的网络环境下想长时间的在终端前台执行某程序,screen 就是必须的工具了。
C. 最后,刚才拔掉键盘显示器,再插回去的动作,用英文怎么说?不就是 detach 和 attach 么
在该同事演示的过程中,screen -x 命令效果是最让人震撼的。我开玩笑说,以后大家都必须在 screen 里工作,这样我就可以做一个真正的监工了。昨晚回家骑车的路上想,这就是远程 PP 啊!如果不得不在不同地点办公,同时又想执行结对编程的团队,是可以考虑利用这个功能来结对的。 只是不知道 X Terminal或远程桌面是否也能实现这样完整共享设备的特性
UPDATE: 有人指出 Eclipse 有一个叫 DocShare 的插件;我看了看,觉得还是不像真正的 PP 那样两人共享一个终端的感觉。
想象一下,甲和乙在地球的两端,开着 screen-x,头戴耳机通过skype通话。
甲:(疯狂击键ing)
乙:停一下,你这里好像忽略了一个情况
甲:(stop typing)..好的,你来吧...(然后看着编辑器光标向上移动了两行,增加了一个判断)
乙:现在好了
甲:我想想,你为什么这样处理...(恍然大悟)...没错没错...不过最好这里再加一个注释.
乙:下面你接着来
.......
纯属 YY
昨天发现快餐店都不卖米饭了...
被迫吃了一碗面..
难道传说中的有毒大米销售到了北京?
Why Python?
在进入搜狐之前,我的 python 经验十分有限。就是会做做 base64.decodestring;学习 pymsnt 的时候接触了一下 twisted;以及,也是比较搞笑的一点,我用 python 最熟的地方居然是 windows 下的开发——访问注册表,用wxPython写界面,用ctypes访问DLL...
搜狐邮件中心开发以前是分成两个小组,一拨C/C++程序员,一拨Java程序员,技术上两者间没什么共同语言。因此我力主引入 python,是想弥合双方的技术范围,让每个程序员,都可能尽多的去接触 E-Mail 的所有业务领域。
一开始是 Twisted 应用,某 java 程序员用它实现了一套监控系统,实时注册IP黑名单系统;MTA 那里则是用它来做 tcptable 查找表的接口。
后来 MTA 那里更夸张的用 pymilter 粘合postfix 和过滤系统,直到我们的某供应商提供了 API 后才不得不改回 C
虽然计划增加 Python 的应用范围,但在规划 AjaxMail 的时候,一开始的确是打算沿用 Java 开发的。原因是三点:
A. 不管 Python 有多少优点,但都绝不应该抛弃以前的旧代码
B. 现有WEB开发人员的知识结构完全是基于Java的
C. 不管 Python 在语言方面有多少优点,但由于主要的业务逻辑都在 Javascript 上,后台究竟用什么语言开发反而是无所谓了。换句话说,Python带来的好处不明显,但风险是极高的
转折点出现在 10 月,两个主力 Java 程序员离开了团队,一个去了微软,一个去了新加坡。我的选择就变成:
1. 招Java程序员,从0开始熟悉现有的代码,学习邮件业务,然后摸索着前进
2. 依赖以前的关系,找几个邮件系统很熟悉的C程序员,用Python或者PHP(类似的事情我在04年干过一次,用PHP替换了eyou.com的CGI)或者什么什么开发,但肯定不是JAVA。
还有一点,我自认永远也不会太深入Java,不可能带着程序员在这条道路上走远。
说起来有点儿造化弄人,我心里确实想全面铺开Python,但理智上还是选择保守,可现实把我推向自己真正想去的地方。
关于这个选择我想更重要的是:万一不得已重头再来,怎样才能尽可能的降低风险呢?
1. 经验。我在这个领域8年了,技术上能做到什么样子还是有把握的。
2. 人才。如果不是因为有一个很得力的程序员,俺就要被迫亲自操刀了;虽然走了两个人,但配了一对更好的组合。
3. 信心。把自己的信心带给团队所有人,消除大家的不确定性。
4. 兼容。代码虽然有变化,但数据格式基本没有变,老的Java代码仍然还是可以使用——我想它应该至少还有半年的生命期。
To be, or not to be. 不管怎么选择,都要事先准备好面对接下来的挑战。
延伸阅读:lighttpd 2.0

最新评论