2008-09-10 10 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。