2008-09-10 11 views
3

我正在尝试使用请求的实际频率分布来自动化服务器的功能测试。 (排序的负载测试中,排序模拟)如何为给定的概率分布生成直方图(用于功能测试服务器)?

我选择了Weibull分配,因为它“之类的”我观察到的分布一致(快速斜升,迅速但不脱落瞬间)

我用这个分布产生应每天发送给定的开始和结束日期

我砍死在一起,在Python的算法之类的作品,但感觉缺憾之间的请求数:

how_many_days = (end_date - start_date).days 
freqs = defaultdict(int) 
for x in xrange(how_many_responses): 
    freqs[int(how_many_days * weibullvariate(0.5, 2))] += 1 
timeline = [] 
day = start_date 
for i,freq in sorted(freqs.iteritems()): 
    timeline.append((day, freq)) 
    day += timedelta(days=1) 
return timeline 

有什么更好的方法来做到这一点?

+0

该算法总是返回预期的响应数量,但它通常不会恰好在开始和结束日期之间适合它们,我不确定这是否可能,除非我手动弄乱频率? – 2008-09-10 11:18:50

+0

它们不能保证在开始日期和结束日期之间适合,因为您使用的是无限支持的概率分布。只要你使用从分配中返回的随机数作为关键字,你就会遇到这个问题。 – Kai 2008-09-11 10:06:51

回答

1

这很快,可能并不准确,但如果您自己计算PDF,那么至少您可以更轻松地在单个时间线上放置几个较小/较大的一个。 dev是控制粗糙度的高斯噪声中的标准偏差。请注意,这是而不是“正确”的方式来产生你想要的,但它很容易。

import math 
from datetime import datetime, timedelta, date 
from random import gauss 

how_many_responses = 1000 
start_date = date(2008, 5, 1) 
end_date = date(2008, 6, 1) 
num_days = (end_date - start_date).days + 1 
timeline = [start_date + timedelta(i) for i in xrange(num_days)] 

def weibull(x, k, l): 
    return (k/l) * (x/l)**(k-1) * math.e**(-(x/l)**k) 

dev = 0.1 
samples = [i * 1.25/(num_days-1) for i in range(num_days)] 
probs = [weibull(i, 2, 0.5) for i in samples] 
noise = [gauss(0, dev) for i in samples] 
simdata = [max(0., e + n) for (e, n) in zip(probs, noise)] 
events = [int(p * (how_many_responses/sum(probs))) for p in simdata] 

histogram = zip(timeline, events) 

print '\n'.join((d.strftime('%Y-%m-%d ') + "*" * c) for d,c in histogram) 
1

你为什么不尝试The Grinder 3加载测试服务器,它带有所有这些以及更多预建的,它支持Python作为脚本语言

+0

不幸的是,这个函数将会在一些功能测试中使用,所以我很乐意尽可能将它全部保存在家庭中。也许模拟比负载测试更好描述 – 2008-09-10 11:23:26

0

而不是给请求的数量为固定值,为什么不使用缩放因子呢?目前,您将请求视为有限的数量,并随机处理这些请求所在的日子。将您每天的请求视为独立,似乎更合理。

from datetime import * 
from random import * 

timeline = [] 
scaling = 10 
start_date = date(2008, 5, 1) 
end_date = date(2008, 6, 1) 

num_days = (end_date - start_date).days + 1 
days = [start_date + timedelta(i) for i in range(num_days)] 
requests = [int(scaling * weibullvariate(0.5, 2)) for i in range(num_days)] 
timeline = zip(days, requests) 
timeline 
+0

这个功能似乎没有产生我正在寻找的形状。如果您查看维基百科文章,我选择了一条红色的曲线,该曲线随着时间的推移迅速增加,似乎模拟了网页浏览量,最初很高,但随着时间的推移,人们对新内容失去兴趣。 – 2008-09-11 09:04:01

+0

事实上,从我的观点来看,整个观点是:请求的数量取决于一天的情况。我不只是试图在一段时间内模拟随机负载。 – 2008-09-11 09:07:05

+0

好的,但你现在正在做的只是近似分布。为什么不使用分配本身,或分配加上一些噪音? 现在,您正在建模一个历史相关的过程,而不使用任何历史记录。 – Kai 2008-09-11 10:41:16

0

我重写上面的代码更短(但也许它现在也混淆?)

timeline = (start_date + timedelta(days=days) for days in count(0)) 
how_many_days = (end_date - start_date).days 
pick_a_day = lambda _:int(how_many_days * weibullvariate(0.5, 2)) 
days = sorted(imap(pick_a_day, xrange(how_many_responses))) 
histogram = zip(timeline, (len(list(responses)) for day, responses in groupby(days))) 
print '\n'.join((d.strftime('%Y-%m-%d ') + "*" * c) for d,c in histogram) 
1

稍长,但你的最后四行可能更具可读性返工:

samples = [0 for i in xrange(how_many_days + 1)] 
for s in xrange(how_many_responses): 
    samples[min(int(how_many_days * weibullvariate(0.5, 2)), how_many_days)] += 1 
histogram = zip(timeline, samples) 
print '\n'.join((d.strftime('%Y-%m-%d ') + "*" * c) for d,c in histogram) 

这总是会在日期范围内丢弃样本,但是您会在时间轴的末尾从[0,1]范围以上的所有样本中获得相应的凹凸。

0
另一个

解决方案是使用Rpy,这使所有的R的功率(包括大量的工具为分布),容易成Python。