在上一篇中我们通过换python的解析器来优化性能。但离实际需求还很远。
  方案2: 优化代码
  工欲善其事,必先利其器。要优化代码,必须先找到代码的瓶颈所在,土的方法是添加log, 或者print, 调试完成还需要删除,比较麻烦。python里面也提供了很多profile工具:profile, cProfile, hotshot, pystats, 但这些工具提供的结果可读性不是很好,不够直观的一眼能看到那个函数或者那一行占用时间多。 python line_profiler 提供了这样的功能,可以很直观的看到哪一行占用的时间多,可谓“快准狠”,下载地址: http://pythonhosted.org/line_profiler/
  安装完line_profiler后,在C:Python27Libsite-packages 目录下会有一个kernprof.py,在可能存在瓶颈的函数上添加 @profile, 如以下例子:
@profile
def create_msg2(self,H,msg):
li = msg.keys()
msg_type=li[0]
ULR_avps=[]
ULR=HDRItem()
ULR.cmd=self.dia.dictCOMMANDname2code(self.dia.MSG_TERM[msg_type])
if msg_type[-1]=='A':
msg=msg[msg_type]
self.dia.setAVPs_by_dic(msg_type,msg,ULR_avps)
ULR.appId=H.appId
ULR.EndToEnd=H.EndToEnd
ULR.HopByHop=H.HopByHop
msg=self.dia.createRes(ULR,ULR_avps)
else:
self.dia.setAVPs(msg_type,msg,ULR_avps)
ULR.appId=self.dia.APPID
self.dia.initializeHops(ULR)
msg=self.dia.createReq(ULR,ULR_avps)
return msg
  运行此文件: kernprof.py -l -v D:projectmpsrcprotocolslibdiametermt.py, 得到如下结果。 从这图中可以很直观的看到setAVPS方法占用了96.6%的时间,再进一步定位到此函数,再次添加@proflie修饰符(可以一次在多个函数上添加Profile), 可以再进一步看到setAVPS函数中各行代码的占用时间比。

  通过一步步的分析中看到,开源协议库中,setAVPS的方法中,查找avp的属性是从一个3000的循环里面查找的,每个AVP都需要循环3000次,一个diameter消息中至少10个avp,每次encoding一个avp需要循环3W次。 我们初始的解决方法是删除了很多我们性能测试中用不到的avp(没办法,测试开发资源有限,很多时候没有很好的设计,先做出满足需求的东西再说。), 但也只是提高到了150左右,离需求还差的很远。所以我们把AVP都改成了字典方式,可以根据名字快速查找到AVP的属性。
  除了代码的优化,同时还增加了encoding avp的线程数,后面章节将会讲到多线程和多进程,对性能的影响。