用python做测试--实现高性能测试工具(2)

来源:http://www.sh-fengwen.com 作者:美高梅游戏平台网站 人气:112 发布时间:2019-09-05
摘要:  方案2: 优化代码 方案3: 改变系统架构 工欲善其事,必先利其器。要优化代码,必须先找到代码的瓶颈所在,最土的方法是添加log,或者print,调试完成还需要删除,比较麻烦。pytho

 

方案2: 优化代码

方案3: 改变系统架构

工欲善其事,必先利其器。要优化代码,必须先找到代码的瓶颈所在,最土的方法是添加log, 或者print, 调试完成还需要删除,比较麻烦。python里面也提供了很多profile工具:profile, cProfile, hotshot, pystats, 但这些工具提供的结果可读性不是很好,不够直观的一眼就能看到那个函数或者那一行占用时间最多。 python line_profiler 提供了这样的功能,可以很直观的看到哪一行占用的时间最多,可谓“快准狠”,下载地址:

在开始多进程之前,先简单说明一下python GIL, 之前自己对他也有些误解。因为python GIL的机制存在,同时运行的线程只有一个,但这个线程在不同时刻可以运行在不同的核上,这个调度是由操作系统完成的,如果你写个死循环,开的线程足够多,是可以把整个系统的CPU消耗干净的,此时你在Linux下通过top可以看到,us 占用的CPU不大,但sy占用的CPU会很大,CPU主要消耗在系统调度上了。下面是测试代码,大家可以试试。

 

 

安装完line_profiler后,在C:Python27Libsite-packages 目录下会有一个kernprof.py,在可能存在瓶颈的函数上添加 @profile, 如以下例子:

import threading

class MultipleThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while 1:
            print here


for i in xrange(100):
    multiple_thread=MultipleThread()
    multiple_thread.start()

multiple_thread.join()

 

 

    @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

既然因为GIL的存在,同时只能运行一个线程,那多线程可以提高效率,当然可以!开个3-4个线程可以明显的提高性能,大概能提高个2-3倍左右吧,但继续增加线程就是副作用了。

 

系统多线程的系统架构:

运行此文件: kernprof.py -l -v D:projectmpsrcprotocolslibdiametermt.py, 得到如下结果。 从这图中可以很直观的看到setAVPS方法占用了96.6%的时间,再进一步定位到此函数,再次添加@proflie修饰符(可以一次在多个函数上添加Profile), 可以再进一步看到setAVPS函数中各行代码的占用时间比。

 

 

发送和接受都不存在瓶颈,主要瓶颈在在红线部分,decode和 encode部分。多线程改成多进程比较简单,工作量不大,只要把需要多进程共享的信息,由Queue改成multiprocessing.Queue()就可以了,把继承的DiameterMsgParser(threading.Thread)改成DiameterMsgParser(multiprocessing.Process),有个比较麻烦的是log的输出,python自带的logging模块在多进程下写同一个文件会引起混乱。这个在后面单独说明。

图片 1

import multiprocessing
import logging

class Worker(multiprocessing.Process):
    def __init__(self,mp_name,input_queue):
        multiprocessing.Process.__init__(self,name=mp_name)
        self.input_queue=input_queue

    def run(self):
        for i in xrange(100):
            self.input_queue.put_nowait(i)
            logging.debug(test +str(i))

 

 

通过一步步的分析中看到,开源协议库中,setAVPS的方法中,查找avp的属性是从一个3000的循环里面查找的,每个AVP都需要循环3000次,我们初始的解决方法是删除了很多我们性能测试中用不到的, 但也只是提高到了150左右,用pypy可以达到 600 的样子。离需求还差的很远。所以我们把AVP都改成了字典方式,可以根据名字快速查找到AVP的属性。

多线程改成多进程后,在sunfire 4170 (16 core , 2.4G ) 上能支持到5000 meesages (双向), CPU占有率 30-40%,用的是标准的python2.7,因为在solaris上没安装成功pypy,所以在此机器上,我没有测试pypy对性能影响多大。但我在一个2核的linux机器上测试python和 pypy,在多进程的情况下的效率,pypy对效率的提升没有达到倍数的级别,没找到什么原因, 后面有CPU核数比较多的机器再测试下。

本文由美高梅游戏平台网站发布于美高梅游戏平台网站,转载请注明出处:用python做测试--实现高性能测试工具(2)

关键词:

最火资讯