Como faço para gerar um histograma para uma determinada distribuição de probabilidade (para testar funcional um servidor)?

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

Pergunta

Estou tentando automatizar o teste funcional de um servidor usando uma distribuição de frequência realista de solicitações.(uma espécie de teste de carga, uma espécie de simulação)

Eu escolhi o Weibull distribuição, pois "mais ou menos" corresponde à distribuição que observei (aumenta rapidamente, diminui rapidamente, mas não instantaneamente)

Eu uso esta distribuição para gerar o número de solicitações que devem ser enviadas a cada dia entre uma determinada data de início e término

Eu criei um algoritmo em Python que funciona, mas parece confuso:

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

Que melhores maneiras existem de fazer isso?

Foi útil?

Solução

Isso é rápido e provavelmente não tão preciso, mas se você mesmo calcular o PDF, pelo menos será mais fácil colocar vários PDFs menores/maiores em uma única linha do tempo. dev é o desvio padrão do ruído Guassiano, que controla a rugosidade.Observe que isso é não a maneira 'certa' de gerar o que você deseja, mas é fácil.

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)

Outras dicas

Por que você não tenta O Moedor 3 para testar a carga do seu servidor, ele vem com tudo isso e muito mais pré-construído e suporta python como linguagem de script

Retrabalho um pouco mais longo, mas provavelmente mais legível, de suas últimas quatro linhas:

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)

Isso sempre elimina as amostras dentro do intervalo de datas, mas você obtém um aumento correspondente no final da linha do tempo de todas as amostras que estão acima do intervalo [0, 1].

Em vez de fornecer o número de solicitações como um valor fixo, por que não usar um fator de escala?No momento, você está tratando as solicitações como uma quantidade limitada e randomizando os dias em que essas solicitações ocorrem.Pareceria mais razoável tratar suas solicitações por dia como independentes.

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

Reescrevi o código acima para ser mais curto (mas talvez esteja muito ofuscado agora?)

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)

Outra solução é usar Rpy, que coloca todo o poder do R (incluindo muitas ferramentas para distribuições) facilmente no Python.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top