0

我必须模拟 Web 应用程序的负载。

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

1 回答 1

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()   
于 2014-01-12T01:41:27.383 回答