주어진 확률 분포에 대한 히스토그램을 어떻게 생성합니까(서버 기능 테스트용)?

StackOverflow https://stackoverflow.com/questions/53786

문제

현실적인 요청 빈도 분포를 사용하여 서버의 기능 테스트를 자동화하려고 합니다.(일종의 부하 테스트, 일종의 시뮬레이션)

나는 ~을 선택했다 와이블 내가 관찰한 분포와 "일종의" 일치하는 분포(빠르게 증가하고 빠르게 감소하지만 즉시는 아님)

이 분포를 사용하여 지정된 시작 날짜와 종료 날짜 사이에 매일 전송되어야 하는 요청 수를 생성합니다.

저는 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

이를 수행하는 더 좋은 방법은 무엇입니까?

도움이 되었습니까?

해결책

이는 빠르고 정확하지 않을 수도 있지만 PDF를 직접 계산하는 경우 적어도 단일 타임라인에 여러 개의 더 작은/큰 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)

다른 팁

시도해 보는 게 어때? 그라인더 3 서버 로드 테스트를 위해 이 모든 기능과 사전 구축된 기능이 함께 제공되며 Python을 스크립팅 언어로 지원합니다.

약간 길지만 마지막 네 줄을 더 읽기 쉽게 재작업했습니다.

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] 범위 위에 있는 모든 샘플의 타임라인 끝에 해당 범프가 표시됩니다.

요청 수를 고정 값으로 제공하는 대신 배율 인수를 대신 사용하는 것은 어떨까요?현재는 요청을 제한된 수량으로 처리하고 해당 요청이 속하는 날짜를 무작위로 지정하고 있습니다.일일 요청을 독립적으로 처리하는 것이 더 합리적으로 보입니다.

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

위의 코드를 더 짧게 다시 작성했습니다. (하지만 지금은 너무 난독화된 것 아닐까요?)

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)

또 다른 해결책은 르피, R의 모든 기능(많은 배포 도구 포함)을 Python에 쉽게 적용할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top