泊松过程和多处理。有更好的解决方案吗?

时间:2013-09-02 10:09:11

标签: python process multiprocessing poisson

我要模拟网络应用程序的负载。

我编写了一个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()

1 个答案:

答案 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()