Come posso generare un istogramma per una determinata distribuzione di probabilità (per testare funzionale un server)?

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

Domanda

Sto cercando di automatizzare i test funzionali di un server utilizzando una distribuzione di frequenza realistica delle richieste.(una sorta di test di carico, una sorta di simulazione)

Ho scelto il Weibull distribuzione poiché "in un certo senso" corrisponde alla distribuzione che ho osservato (aumenta rapidamente, diminuisce rapidamente ma non istantaneamente)

Utilizzo questa distribuzione per generare il numero di richieste che dovrebbero essere inviate ogni giorno tra una determinata data di inizio e di fine

Ho messo insieme un algoritmo in Python che funziona ma sembra complicato:

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

Quali modi migliori ci sono per farlo?

È stato utile?

Soluzione

Questo è veloce e probabilmente non così accurato, ma se calcoli tu stesso il PDF, almeno rendi più semplice posizionare diversi PDF più piccoli/più grandi su un'unica sequenza temporale. dev è la deviazione std del rumore guassiano, che controlla la rugosità.Nota che questo è non il modo "giusto" per generare ciò che desideri, ma è facile.

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)

Altri suggerimenti

Perché non ci provi? Il macinatore 3 per caricare testare il tuo server, viene fornito con tutto questo e altro ancora precostruito e supporta Python come linguaggio di scripting

Rielaborazione leggermente più lunga ma probabilmente più leggibile delle tue ultime quattro righe:

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)

In questo modo i campioni rientrano sempre nell'intervallo di date, ma alla fine della sequenza temporale si ottiene un aumento corrispondente da tutti i campioni che si trovano al di sopra dell'intervallo [0, 1].

Invece di fornire il numero di richieste come valore fisso, perché non utilizzare invece un fattore di scala?Al momento, stai trattando le richieste come una quantità limitata e randomizzando i giorni in cui cadono tali richieste.Sembrerebbe più ragionevole considerare le tue richieste giornaliere come indipendenti.

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

Ho riscritto il codice sopra per essere più breve (ma forse ora è troppo confuso?)

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)

Un'altra soluzione è usare Rpy, che inserisce facilmente tutta la potenza di R (inclusi molti strumenti per le distribuzioni) in Python.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top