Comment générer un histogramme pour une distribution de probabilité donnée (pour tester fonctionnel un serveur) ?

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

Question

J'essaie d'automatiser les tests fonctionnels d'un serveur en utilisant une distribution de fréquence réaliste des requêtes.(sorte de test de charge, sorte de simulation)

j'ai choisi le Weibull la distribution car elle correspond "en quelque sorte" à la distribution que j'ai observée (elle augmente rapidement, diminue rapidement mais pas instantanément)

J'utilise cette distribution pour générer le nombre de requêtes qui doivent être envoyées chaque jour entre une date de début et de fin donnée

J'ai piraté un algorithme en Python qui fonctionne en quelque sorte, mais il semble fastidieux :

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

Existe-t-il de meilleures façons de procéder ?

Était-ce utile?

La solution

C'est rapide et probablement pas très précis, mais si vous calculez le PDF vous-même, vous facilitez au moins la pose de plusieurs fichiers plus petits/plus grands sur une seule chronologie. dev est l'écart type du bruit guassien, qui contrôle la rugosité.Notez que c'est pas la « bonne » façon de générer ce que vous voulez, mais c'est 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)

Autres conseils

Pourquoi n'essayes-tu pas Le broyeur 3 pour tester la charge de votre serveur, il est livré avec tout cela et bien plus encore, et il prend en charge Python comme langage de script

Reprise légèrement plus longue mais probablement plus lisible de vos quatre dernières lignes :

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)

Cela supprime toujours les échantillons dans la plage de dates, mais vous obtenez une augmentation correspondante à la fin de la chronologie pour tous les échantillons situés au-dessus de la plage [0, 1].

Au lieu de donner le nombre de requêtes sous forme de valeur fixe, pourquoi ne pas utiliser un facteur d'échelle ?Pour le moment, vous traitez les demandes comme une quantité limitée et vous randomisez les jours où ces demandes tombent.Il semblerait plus raisonnable de traiter vos demandes journalières de manière indépendante.

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

J'ai réécrit le code ci-dessus pour qu'il soit plus court (mais peut-être qu'il est trop obscur maintenant ?)

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)

Une autre solution consiste à utiliser Rép., qui met facilement toute la puissance de R (y compris de nombreux outils pour les distributions) dans Python.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top