我要模拟网络应用程序的负载。
我编写了一个python代码,在指数分布后生成随机请求。
请求是一个简单的url-get:我测量响应时间并将其存储在文件中。
因此,在给定时间内,代码会创建一个执行请求的新进程,然后他会在random.expovariate(lambd)给出的随机时间内休眠。
当我开始请求时,我还存储一个时间戳来检查平均值是否接近1 / lambda。
我设置lambda>时出现问题20:平均值高于1 / lambda,这导致执行缓慢。
我测试随机生成器非常好,所以我认为问题是系统必须创建一个新进程。
有没有办法加速这个阶段?
也许流程创建有一些限制?
我忘了说python版本是2.7.3而且我无法升级它。
使用pypy有一些性能改进,但问题仍然存在。
这里是代码:
def request(results,url):
start = time.time()
try:
r = requests.get(url)
except:
noactions
else:
# Append results (in seconds)
results.write("{0},{1}\n".format(start,r.elapsed.microseconds/1e6))
def main():
# Open results file
results = open(responseTimes.txt",'a')
processes = []
# Perform requests for time t (seconds) with rate lambda=l
start = time.time()
elapsed = 0
while (t > elapsed):
p = Process(target=request, args=(results,url,))
p.daemon = True
p.start()
processes.append(p)
time.sleep(random.expovariate(l))
elapsed = time.time() - start
# Wait for all processes to finish
[p.join() for p in processes]
# Close the file
results.close()
if __name__ == "__main__":
main()
答案 0 :(得分:0)
<强>分析强>
您可能正在创建太多进程并且会降低系统速度。创建一个过程通常需要不到1.0 / 20秒,当有太多时,这可能会增加到1.0 / 20以上,导致观察到的速度:
from timeit import timeit
from multiprocessing import Process
def launch():
Process().start()
for n in [1, 10, 100]:
print timeit(stmt=launch, number=n)
# time in seconds to launch a process
# as measured on a 2.7 GHz Core i7 Mac Mini with OSX 10.9
0.000946998596191
0.00857591629028
0.0778558254242
根据工作量,CPU,内存等因素,这些数字可能因机器而异。
<强>解决方案强>
Thas说,你应该使用一种方法来开始说10-20个进程(甚至更好:线程,因为它们需要更少的开销),每个进程以1 / lambda的速率发出请求:
def worker(n, results, url, l):
print "worker %d started" % n
while(True):
# request the first URL
request(results, url)
# wait for next event with poission-process time lag
time.sleep(random.expovariate(l))
def main():
# your code to initialise
...
# set parameters
t = 100
l = 20
# start n workers
n = 10
processes=[]
for i in range(0,n):
print "starting worker %d" % i
p = Process(target=worker, args=(i,results,url,l,))
p.start()
processes.append(p)
# now wait for requested time
time.sleep(t)
# stop workers
for p in processes:
p.terminate()