我们的业务代码就是
counter = 0
if __name__ == '__main__':
def logic(d_in):
global counter
counter += 1
if counter %100000 ==0:
print counter,time.time()
return(d_in[::-1])
reverseD = nbNet('0.0.0.0', 9099, logic)
reverseD.run()
说白了就是 每响应10w下答应一下时间
我们测试端代码
#!/usr/bin/env python
import socket, sys, os
HOST = '127.0.0.1'
PORT = 9099
CNT = int(sys.argv[2])
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
cmd = sys.argv[1]
data = "%010d%s"%(len(cmd), cmd)
while True:
s.send(data * CNT)
s.recv(len(data) * CNT)
但是我们的客户端是不可能打到server端的性能瓶颈的,我们可以开启多个终端,启动多个实例,这样达到我们性能要求
我们首先看下没有优化之前的性能
我们虚拟机的性能是:一核心CPU没有超线程 2.5G 内存2G
我们从300w次请求之后选取后面100w次的时间
3000000 1527159028.98
3100000 1527159031.62
3200000 1527159034.16
3300000 1527159036.72
3400000 1527159039.27
3500000 1527159041.82
3600000 1527159044.38
3700000 1527159047.01
3800000 1527159049.56
3900000 1527159052.12
4000000 1527159054.69
我们计算下每10w次请求的时间(取小数点后两位)
[0] 2.63s
[1] 2.54s
[2] 2.56s
[3] 2.55s
[4] 2.56s
[5]2.62s
[6] 2.55s
[7] 2.56s
[8] 2.57s
[9]2.56s
最差 2.63s QPS 约等于 38022
最好 2.54s QPS 约等于 39370
==============================================================
在python内建了一个 profiler工具,可以帮我们定位性能瓶颈
服务端调用方法
python -m cProfile -s cumulative nbNetFramework.py
-s cumulative 的意思是按照系统调用的总体耗时排序
客户端调用方法
python loadrun.py a 100
python loadrun.py a 100
执行一段时间后 结束server的时候会输出这段时间代码中的方法执行时间情况
root@work:/home/rico/python/rebootMon/nbNet# python -mcProfile -s cumulative nbNetFramework.py
100000 1527160075.61
200000 1527160079.19
300000 1527160082.8
^C 11986059 function calls (11985241 primitive calls) in 14.675 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.001 0.001 14.675 14.675 nbNetFramework.py:4(<module>)
1 1.693 1.693 14.654 14.654 nbNetFramework.py:166(run)
1088050 0.615 0.000 10.292 0.000 nbNetFramework.py:192(state_machine)
725366 0.622 0.000 5.588 0.000 nbNetFramework.py:271(read2process)
362683 0.670 0.000 4.089 0.000 nbNetFramework.py:307(write2read)
725366 1.722 0.000 2.981 0.000 nbNetFramework.py:66(read)
1088050 2.669 0.000 2.669 0.000 {method 'poll' of 'select.epoll' objects}
362683 1.209 0.000 1.985 0.000 nbNetFramework.py:232(process)
362683 0.605 0.000 1.691 0.000 nbNetFramework.py:124(write)
362685 0.719 0.000 1.382 0.000 nbNetFramework.py:21(setFd)
725366 1.070 0.000 1.070 0.000 {method 'recv' of '_socket.socket' objects}
362683 0.894 0.000 0.894 0.000 {method 'send' of '_socket.socket' objects}
725365 0.740 0.000 0.740 0.000 {method 'modify' of 'select.epoll' objects}
362692 0.303 0.000 0.423 0.000 socket.py:227(meth)
362683 0.320 0.000 0.320 0.000 nbNetFramework.py:339(logic)
2905468/2905319 0.250 0.000 0.250 0.000 {len}
362685 0.240 0.000 0.240 0.000 nbNetUtils.py:164(__init__)
363892 0.192 0.000 0.192 0.000 {isinstance}
362725 0.067 0.000 0.067 0.000 {getattr}
362688 0.053 0.000 0.053 0.000 {method 'fileno' of '_socket.socket' objects
ncalls -- 调用多少次
#自己调用的时间,不包括其他十年
tottime 调用时耗
percall 每次调用的时间
#包括子函数时间
cumtime调用耗时
percall 每次调用耗时
这样我们就知道那个方法比较耗费时间了。
然后通过 line_profiler来优化具体的行
#pip install line_profiler 安装
在比较耗时的方法上面加上@profile 这个装饰(这里我们看到之前的read方法比较耗时)
# kernprof -l -v ./nbNet.py 执行命令
然后我们执行客户端代码
然后等一段时间结束
Function: read at line 45
Line # Hits Time Per Hit % Time Line Contents
==============================================================
45 @profile
46 def read(self, fd):
47 """fd is fileno() of socket"""
48 87910 118605.0 1.3 7.1 try:
49 87910 104105.0 1.2 6.2 sock_state = self.conn_state[fd]
50 87910 71153.0 0.8 4.2 conn = sock_state.sock_obj
51 87910 79448.0 0.9 4.7 if sock_state.need_read <= 0:
52 raise socket.error
53 87910 433116.0 4.9 25.8 one_read = conn.recv(sock_state.need_read)
54 87910 118447.0 1.3 7.1 if len(one_read) == 0:
55 raise socket.error
56 87910 122770.0 1.4 7.3 sock_state.buff_read += one_read
57 87910 92267.0 1.0 5.5 sock_state.have_read += len(one_read)
58 87910 99366.0 1.1 5.9 sock_state.need_read -= len(one_read)
59
60
61 87910 78578.0 0.9 4.7 if sock_state.have_read == 10:
62 43955 126373.0 2.9 7.5 header_said_need_read = int(sock_state.buff_read)
63 43955 41639.0 0.9 2.5 if header_said_need_read <= 0:
64 raise socket.error
65 43955 45788.0 1.0 2.7 sock_state.need_read += header_said_need_read
66 43955 39130.0 0.9 2.3 sock_state.buff_read = ''
67 43955 33228.0 0.8 2.0 return "readcontent"
68 43955 37326.0 0.8 2.2 elif sock_state.need_read == 0:
69 43955 35561.0 0.8 2.1 return "process"
70 else:
71 return "readmore"
72 except (socket.error, ValueError), msg:
73 try:
74 if msg.errno == 11:
75 return "retry"
76 except:
77 pass
78 return 'closing'