BARBIER Jérôme — HUSSON Augustin
library(ggplot2)
library(plyr)
# fonction d'initialiser de la liste des temps d'arrivée
initT1 <- function(n, An) {
t1 <- c()
t1[1] <- 0
i <- 2
while (i <= n) {
t1[i] <- t1[i - 1] + An[i]
i <- i + 1
}
t1
}
# fonction qui renvoit la liste des temps de service suivant la fonction
# désirée
typeFunction <- function(n, mu, fonction) {
Sn <- c()
if (fonction == "exp") {
Sn <- rexp(n, mu)
} else if (fonction == "deter") {
Sn <- array(1, n)
} else if (fonction == "unif") {
Sn <- runif(n, 0.5, 1.5)
} else if (fonction == "erlang0.5_2") {
Sn <- rgamma(n, shape = 0.5, scale = 1/0.5)
} else if (fonction == "erlang0.1_10") {
Sn <- rgamma(n, shape = 0.1, scale = 1/0.1)
}
Sn
}
mode non-préemptif
Pour élaborer l'algorithme permettant de modéliser une liste lifo avec un mode non-préemptif, on s'est basé sur ce qui a été fait sur les listes fifo. C'est à dire qu'on reprend la liste t1 des temps d'arrivée des clients avec sa formule de récurrence associée. C'est à dire t1[i] = t1[i-1]+An[i] avec An le tableau des interarrivées.
Pour trouver comment on calcul la liste t_2 qui représente les temps de sortie des clients, on distingue deux cas. Soit la liste d'attente (lifo) est vide (état initial) soit il y a des clients à l'intérieur.
Cas initial : On prend le premier client de la liste qui arrive donc avec un temps \( t_1 \). Vu qu'il n'y a personne d'autre en attente, le serveur traite immédiatement la requête du client. On a alors \( t_2 \) = \( t_1 \) + \( S_n \) avec \( S_n \) la liste des temps de service du serveur. \( t_2 \) dépend ici de \( t_1 \) car le serveur ne traitait personne.
Pendant que le serveur traite ce client \( t_1 \) avec le service \( S_n \), on peut avoir d'autres clients qui arrivent. Pour savoir s'ils sont arrivés pendant le temps de traitement du client courant, il suffit de savoir si leur temps d'arrivée est inférieur au temps de sortie du client courant. C'est à dire si leur temps t1 est inférieur au \( t_2 \) du client courant.
Ainsi si \( t_1 \) > \( t_2 \) alors cela signifie que personne n'est arrivée pendant que le serveur traitait la requête du client courant. On reste à ce moment là dans le cas initial.(ie on recommence ce qu'on a dit ci-dessus)
Dans le cas où \( t_1 \) = \( t_2 \), on a choisit de dire qu'à ce moment là il n'y a tout de même personne qui était arrivée pendant le temps de traitement car ce cas arrive avec une probabilité quasiment nulle.
Dans le cas où il y a des clients qui sont arrivés pendant le traitement en cours, ils sont alors empilés dans la liste lifo au fur et à mesure de leur arrivée. Dans ce cas là on passera dans le cas intérmédiaire.
Cas intermédiaire : C'est donc le cas où la liste lifo n'est pas vide.
Dans ce cas là , on prend le premier client qui est au-dessus de la pile (ie dernier client de la liste lifo). On calcul son temps d'arrivée qui vaut donc t2[j]=t2[j-1]+Sn[j] pour le jeme client traité. Le temps \( t_2 \) dépend ici du temps \( t_2 \) précédent car on est dans le cas où il y a eu des arrivées pendant un traitement d'un client précédent. Donc une fois que le client précédent est partit, on enchaine directement avec celui en tête de pile. D'où le fait qu'on prend le temps \( t_2 \) du client précédent.
Une fois que le temps \( t_2 \) est calculé, on calcul également le temps \( R_n \) avec \( t_2 \) -\( t_1 \) où \( t_1 \) est le temps d'arrivée du client traité qui est stocké dans la liste lifo. Une fois que \( R_n \) est calculé on dépile un coup la liste lifo.
Une fois que \( R_n \) est calculé, on cherche de nouveau à savoir si pendant le temps de traitement du client courant il y a eu des arrivées d'autre client. De même que pour le cas initial on empilera les nouveaux clients au fur et à mesure de leur arrivée.
Si la liste lifo est vide, cela signifie qu'il n'y a pas eu d'arrivée et que tous les clients contenus dans la liste lifo ont été traités, il faut donc repasser dans le cas initial.
non_preemptif<-function(lambda,mu,n,fonction){
init<-TRUE;
i<-1; # indice de T1
j<-1; # indice de T2 et de Rn
k<-1; # indide de la liste lifo
An<-rexp(n, lambda); # tableau des interarrivées
Sn<-typeFunction(n,mu,fonction) #tableau des services
lifo<-c(); # liste lifo
t1 <- initT1(n,An); #tableau des temps d'arrivée
t2 <- c(); # tableau des temps de sortie des clients
rn <- c(); # tableau des temps finaux
while(j<=n){
if(init){ # cas initial
k<-1;
t2[j]<-t1[i]+Sn[j]; #on calcul t2 du ieme client qui est arrivé avec le temps t1[i]
rn[j]<-t2[j]-t1[i];
i<-i+1;j<-j+1;
while((i<=n)&&(t1[i]<t2[j-1])){ # on cherche à savoir s'il y a eu des arrivées pendant que le ieme client était traité.
lifo[k]<-t1[i]; # le temps d'arrivée est empilé dans la liste lifo
k<-k+1;
i<-i+1;
}
if(k!=1) # dans ce cas là cela signifie qu'il y a eu des arrivées pendant le temps de traitement
init<-FALSE;
}
else{
t2[j]<-t2[j-1]+Sn[j]; #on calcul t2 du jeme client qui est en queue de la liste lifo
rn[j]<-t2[j]-lifo[k-1]; #on prend le dernier client arrivé qui est donc stocké en haut de la pile
j<-j+1;
k<-k-1; #on supprime l'élément en fin de tableau avant d'en rajouter. Donc autant écraser le dernier élément de la liste lifo par un nouvel élément. Cela évite de recommencer une allocation de mémoire supplémentaire vu que la case mémoire existera déjà. C'est pourquoi on décrémente simplement l'indice de la liste lifo de un au lieu de supprimer réellement le dernier élément.
while((i<=n)&&(t1[i]<t2[j-1])){ # de nouveau on cherche à savoir s'il y a eu des nouveaux arrivants
lifo[k]<-t1[i]; # les temps d'arrivée sont stockés dans la liste lifo et empilés au fur et à mesure.
k<-k+1;
i<-i+1;
}
if(k==1) # signifie que la liste lifo est vide et qu'il faut repasser à l'état initial.
init<-TRUE;
}
}
df = data.frame(Type = "non_premp" ,Fonction = fonction,Lambda = lambda,R = rn);
df;
}
mainNonPreemptif <- function(lambdamin,lambdamax,stepLambda, nloop,fonction){
i<-lambdamin;
df<-non_preemptif(i,1,nloop,fonction);
i<-i+stepLambda;
while(i<=lambdamax){
df<-rbind(df,non_preemptif(i,1,nloop,fonction));
i<-i+stepLambda;
}
df;
}
# fonction de confort
non_Preemptif_total <- function(lambdamin,lambdamax,stepLambda,nloop){
df<-mainNonPreemptif(lambdamin,lambdamax,stepLambda,nloop,"exp");
df<-rbind(df,mainNonPreemptif(lambdamin,lambdamax,stepLambda,nloop,"deter"));
df<-rbind(df,mainNonPreemptif(lambdamin,lambdamax,stepLambda,nloop,"unif"));
df<-rbind(df,mainNonPreemptif(lambdamin,lambdamax,stepLambda,nloop,"erlang0.5_2"));
df<-rbind(df,mainNonPreemptif(lambdamin,lambdamax,stepLambda,nloop,"erlang0.1_10"));
dfFinal<-ddply(df,c("Type","Fonction","Lambda"),summarize,Time=mean(R),InterConfi = sd(R)/sqrt(length(R)));
ggplot(dfFinal, aes(x = Lambda, y = Time, ymin = Time - InterConfi, ymax = Time +
InterConfi, color = Fonction)) + geom_pointrange()+geom_errorbar();
}
Mode préemptif On repart du mode non-préemptif pour faire ce nouveau mode. On ajoute une liste \( s_2 \) qui permettra d'avoir les nouveaux temps de service du client qui se ferait préempter. On distingue donc de nouveau le cas où la liste lifo est vide et le cas où elle ne l'est justement pas:
Cas initial : Comme avant on calcul le temps \( t_2 \) de la même manière. Cependant on sauvegarde directement le temps \( t_1 \) dans la liste lifo, chose qu'on ne faisait pas avant dans le mode non-préempté. Cette sauvegarde est éffectuée dans le cas d'une potentielle préemption. Car si le cas arrive, le serveur interrompera son traitement du client courant pour traiter le client qui vient d'arrivée. De ce fait il est nécessaire de tout de suite sauvegarder le temps d'arrivée du premier client.
On cherche ensuite à savoir s'il y a un client qui est arrivée pendant le temps de service. Si ce n'est pas le cas, on calcul alors \( R_n \) et on dépile le client courant car il a été traité.
Si il y a eu préemption, alors: a) dans le mode avec reprise, on calculera la différence entre \( t_2 \) et \( t_1 \) du nouveau client ce qui déterminera ainsi le temps de service restant pour le client qui s'est fait préempter. Ce nouveau temps de service est alors stocké dans \( s_2 \) au même indice que celui où se trouve le client préempté dans la liste lifo.
b) dans le mode avec redémarrage, on stocke dans \( s_2 \) le temps de service total du client préempté en ayant toujours la correspondance des indices entre \( s_2 \) et la liste lifo (on retrouve ainsi à l'indice k dans s2 le temps de service du client à l'indice k de la liste lifo)
c) dans le mode avec réinitialisation, on fait de même mais cette fois en calculant un tout nouveau temps de service qu'on stocke de la même manière que décrite précédemment.
En prévision des traitements suivants, on stocke ensuite le temps de service du prochain client dans \( s_2 \). Enfin, on modifie le temps \( t_2 \) afin qu'il soit positionné sur le temps t1 du nouveau client qui vient d'arrivée et qui a donc un temps d'arrivée inférieur au temps de sortie \( t_2 \) du client préempté.
Cas intermédiaire : Comme d'habitude on commence par calculer le temps \( t_2 \). Il a cependant quelques différences par rapport à avant. Tout d'habord on ne sauvegarde pas le temps \( t_1 \) au préalable dans la liste lifo comme on le fait dans le cas initial car on a déjà le temps \( t_1 \) en tête de pile (et/ou en queue de la liste lifo). Ensuite on ne prend pas le temps de service dans \( s_1 \) mais dans \( s_2 \), car on ne sait pas si c'est un client qui a déjà été préempté ou si c'est un client qui vient d'arrivée. D'où la nécessité de sauvegarder au préalable le temps \( s_1 \) dans \( s_2 \) dans le cas d'un nouveau client.(chose qu'on a faite dans le cas initial vers la fin de la procédure)
Une fois ce temps calculé, on cherche classiquement si le client courant s'est fait préempter. La suite de la procédure est la même que pour le cas initial à une exception près: dans le cas d'une préemption, si on est en mode “redémarrage”, on ne cherchera pas à sauvegarder le temps de service du client courant car on l'aura déjà fait au coup précédent.
preemp<-function(lambda,mu,n,mode,fonction){
init<-TRUE;
i<-1; # indice de T1
j<-1; # indice de T2 de taille >= m
k<-1; # incide de la liste lifo et de s2 qui est la liste des nouveaux temps de service
l<-1; # indice de Rn
m<-1; #indice de la liste s1
An<-rexp(n, lambda);
s1 <-typeFunction(n,mu,fonction);
s2 <- c();
lifo<-c();
t1 <- initT1(n,An);
t2 <- c();
rn <- c();
while(l<=n){
if(init){ # signifie qu'on est dans l'état initial et donc que la liste lifo est vide
k<-1; # pas nécessairement utile car k vaut nécessairement 1 pour pouvoir rentrer dans cet état initial. On l'a placé par sécurité.
lifo[k]<-t1[i]; #on sauvegarde l'état d'arrivée du ieme client en prévision d'une potentielle préemption.
t2[j]<-t1[i]+s1[m]; # on calcul son temps de sortie comme dans le mode non-préemptif
i<-i+1;j<-j+1;k<-k+1;m<-m+1;
if((i<=n)&&(t1[i]<t2[j-1])){ #on prend le premier client qui arrive pendant que le ieme client est traité
lifo[k]<-t1[i];
k<-k+1;i<-i+1;
}
if(k==2){#signifie qu'on n'est pas rentré dans le premier if
rn[l]<-t2[j-1]-t1[i-1]; # dans ce cas là on calcul le rn correspond à ce client.
l<-l+1;
k<-k-1; # on "dépile" donc le ieme client vu qu'il n'a pas été préempté et a donc été traité complètement
}
else{ # k == 3 et cela signifie qu'un client est arrivé pendant le traitement du ieme client
init<- FALSE;
# suivant le mode de préemption choisit on se retrouvera dans un des trois cas ci-dessous
if(mode == "reprise"){
s2[k-2]<-t2[j-1]-t1[i-1]; # on calcul le temps de service restant.
}else if(mode == "redemarrage"){
s2[k-2]<-s1[m-1]; # on récupère le temps de service total qu'on prend donc dans la liste S1
}else if(mode == "reinit"){
s2[k-2]<-typeFunction(1,mu,fonction); # on recalcul un temps de service.
}
s2[k-1]<-s1[m]; # en prévision du client en tête de pile, on sauvegarde son temps de traitement dans la liste s2
t2[j-1]<-t1[i-1]; # on reprend à partir du t1 qui a interrompu le premier t1
m<-m+1;
}
}
else{
test<-k; # on sauvegarde k afin de savoir par la suite si le client courant sera préempté.
t2[j]<-t2[j-1]+s2[k-1]; # on calcul comme d'habitude son temps t2
j<-j+1;
if((i<=n)&&(t1[i]<t2[j-1])){ #de nouveau on cherche à savoir si le client courant a été préempté.
lifo[k]<-t1[i]; #si c'est le cas, on stock en tête de pile le temps d'arrivée du nouveau client
k<-k+1;i<-i+1;
}
if(test==k){ #signifie qu'on n'est pas rentré dans le premier if et qu'il n'y donc pas eu de préemption
rn[l]<-t2[j-1]-lifo[k-1]; #dans ce cas là uniquement on calcul alors le temps rn
l<-l+1;
k<-k-1;
}
else{ #le client en tête de pile a été préempté. On fait le même traitement que pour le cas initial sauf concernant le mode : redemarrage
if(mode == "reprise"){
s2[k-2]<-t2[j-1]-t1[i-1];
#}else if(mode == "redemarrage"){
#s2[k-2]<-s1[m-1]; il n'y a pas besoin d'enregistrer la valeur du temps de service car elle a déjà été enregistrée au coup précédent par la ligne s2[k-1]<-s1[m]; De ce fait
}else if(mode == "reinit"){
s2[k-2]<-typeFunction(1,mu,fonction);
}
s2[k-1]<-s1[m];
t2[j-1]<-t1[i-1];
m<-m+1;
}
if(k==1) # la liste lifo est vide il faut donc retourner dans le cas initial.
init<-TRUE;
}
}
df = data.frame(Type=mode,Fonction=fonction,Lambda = lambda,R = rn);
df;
}
mainPreemptif <- function(lambdamin,lambdamax,stepLambda, nloop,mode,fonction){
i<-lambdamin;
df<-preemp(i,1,nloop,mode,fonction);
i<-i+stepLambda;
while(i<=lambdamax){
df<-rbind(df,preemp(i,1,nloop,mode,fonction));
i<-i+stepLambda;
}
df;
}
# procedure de confort : elles permettent juste d'afficher toutes les courbes d'un mode donné.
preemptifReprise<-function(lambdamin,lambdamax,stepLambda,nloop){
df<-mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"reprise","exp");
df<-rbind(df,mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"reprise","deter"));
df<-rbind(df,mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"reprise","unif"));
df<-rbind(df,mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"reprise","erlang0.5_2"));
df<-rbind(df,mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"reprise","erlang0.1_10"));
dfFinal<-ddply(df,c("Fonction","Lambda"),summarize,Time=mean(R),InterConfi = sd(R)/sqrt(length(R)));
ggplot(dfFinal, aes(x = Lambda, y = Time, ymin = Time - InterConfi, ymax = Time +
InterConfi, color = Fonction)) + geom_pointrange()+geom_errorbar();
}
preemptifRedemarrage <- function(lambdamin,lambdamax,stepLambda,nloop){
df<-mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"redemarrage","exp");
df<-rbind(df,mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"redemarrage","deter"));
df<-rbind(df,mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"redemarrage","unif"));
df<-rbind(df,mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"redemarrage","erlang0.5_2"));
df<-rbind(df,mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"redemarrage","erlang0.1_10"));
dfFinal<-ddply(df,c("Fonction","Lambda"),summarize,Time=mean(R),InterConfi = sd(R)/sqrt(length(R)));
ggplot(dfFinal, aes(x = Lambda, y = Time, ymin = Time - InterConfi, ymax = Time +
InterConfi, color = Fonction)) + geom_pointrange()+geom_errorbar();
}
preemptifReinit <- function(lambdamin,lambdamax,stepLambda,nloop){
df<-mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"reinit","exp");
df<-rbind(df,mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"reinit","deter"));
df<-rbind(df,mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"reinit","unif"));
df<-rbind(df,mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"reinit","erlang0.5_2"));
df<-rbind(df,mainPreemptif(lambdamin,lambdamax,stepLambda,nloop,"reinit","erlang0.1_10"));
dfFinal<-ddply(df,c("Fonction","Lambda"),summarize,Time=mean(R),InterConfi = sd(R)/sqrt(length(R)));
ggplot(dfFinal, aes(x = Lambda, y = Time, ymin = Time - InterConfi, ymax = Time +
InterConfi, color = Fonction)) + geom_pointrange()+geom_errorbar();
}
question2 <- function(lambdamin, lambdamax, stepLambda, nloop) {
df <- mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "reinit", "exp")
df <- rbind(df, mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "redemarrage",
"exp"))
df <- rbind(df, mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "reprise",
"exp"))
df <- rbind(df, mainNonPreemptif(lambdamin, lambdamax, stepLambda, nloop,
"exp"))
dfFinal <- ddply(df, c("Type", "Lambda"), summarize, Time = mean(R), InterConfi = sd(R)/sqrt(length(R)))
ggplot(dfFinal, aes(x = Lambda, y = Time, ymin = Time - InterConfi, ymax = Time +
InterConfi, color = Type)) + geom_pointrange() + geom_errorbar()
}
question2(0.2, 0.8, 0.2, 1000)
Bon la courbe est assez peu lisible avec un pas de 0.2 donné dans l'énoncé. Du coup on va refaire la courbe avec un pas plus fin, par exemple 0.02. On remarque aussi que la courbe représentant le mode préemptif avec redémarrage explose littéralement Du coup les autres courbes sont complètements écrasées. On va donc tronquer également le graphe.
question2Ameliorer <- function(lambdamin, lambdamax, stepLambda, nloop) {
df <- mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "reinit", "exp")
df <- rbind(df, mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "redemarrage",
"exp"))
df <- rbind(df, mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "reprise",
"exp"))
df <- rbind(df, mainNonPreemptif(lambdamin, lambdamax, stepLambda, nloop,
"exp"))
dfFinal <- ddply(df, c("Type", "Lambda"), summarize, Time = mean(R), InterConfi = sd(R)/sqrt(length(R)))
ggplot(dfFinal, aes(x = Lambda, y = Time, ymin = Time - InterConfi, ymax = Time +
InterConfi, color = Type)) + geom_pointrange() + geom_errorbar() + ylim(0,
10)
}
question2Ameliorer(0.2, 0.8, 0.02, 10000)
## Warning: Removed 17 rows containing missing values (geom_segment).
## Warning: Removed 17 rows containing missing values (geom_point).
C'est beaucoup mieux. On voit ainsi que la courbe du mode préemptif avec redémarrage part très rapidement vers le haut. Par contre les 3 autres courbes restent assez confondu entre elle. Étonnament d'ailleurs le mode préemptif avec réinitilisation du temps de service n'explose pas comme avec le redémarrage et reste équivalent au mode non préemptif ou au mode préemptif avec reprise. Étonnament car on ne voit pas vraiment où se trouve la différence entre nouveau temps de service et reprendre le temps de service initial car dans les deux cas on recommence depuis le début.
On va tout d'abord tracer toutes les fonctions dans chaque mode donnée afin de déterminer là où les lois qui sont les plus performantes pour un mode donné. De cette façon, on pourra comparer les lois trouvées à l'étape précédente tout mode confondu afin de voir si une loi sort du lot ou non.
Comme pour la question précédente on se tiendra à un lambda max égal à 0.8. Après avoir simulé plusieurs fois les différents modes on se rend rapidement compte qu'après 0.8 toutes les lois font décoler les courbes et les points n'ont plus une très grande signification.
Donc pour le moment traçons les lois pour le mode non-préemptif :
non_Preemptif_total(0.2, 0.8, 0.02, 1000)
Bon de la même façon que pour la question 2, à cause de la loi d'erlang de paramètre 0.1,10 qui explose rapidement, les autres courbes sont complètements écrasées, on va donc tronquer de nouveau le graphe.
non_Preemptif_version_tronquée <- function(lambdamin, lambdamax, stepLambda,
nloop) {
df <- mainNonPreemptif(lambdamin, lambdamax, stepLambda, nloop, "exp")
df <- rbind(df, mainNonPreemptif(lambdamin, lambdamax, stepLambda, nloop,
"deter"))
df <- rbind(df, mainNonPreemptif(lambdamin, lambdamax, stepLambda, nloop,
"unif"))
df <- rbind(df, mainNonPreemptif(lambdamin, lambdamax, stepLambda, nloop,
"erlang0.5_2"))
df <- rbind(df, mainNonPreemptif(lambdamin, lambdamax, stepLambda, nloop,
"erlang0.1_10"))
dfFinal <- ddply(df, c("Type", "Fonction", "Lambda"), summarize, Time = mean(R),
InterConfi = sd(R)/sqrt(length(R)))
ggplot(dfFinal, aes(x = Lambda, y = Time, ymin = Time - InterConfi, ymax = Time +
InterConfi, color = Fonction)) + geom_pointrange() + geom_errorbar() +
ylim(0, 10)
}
non_Preemptif_version_tronquée(0.2, 0.8, 0.02, 10000)
## Warning: Removed 9 rows containing missing values (geom_segment).
## Warning: Removed 9 rows containing missing values (geom_point).
C'est beaucoup mieux comme ça. On voit tout de suite que les lois les plus performantes pour ce mode sont les lois uniforme et déterministe. En effet elles restent assez plates comparées aux autres lois qui décolent assez vite.
On passe maintenant aux différents modes de la version avec préemption.
Version avec reprise :
preemptifReprise(0.2, 0.8, 0.02, 1000)
Bon ici aucune lois ne se distinguent. Elles suivent toute la même progression. On remarque que les temps sont assez courts, ils ne dépassent quasiment pas voir pas du tout la valeur 5.
Version avec redémarrage :
preemptifRedemarrage(0.2, 0.8, 0.02, 1000)
Les courbent s'envolent de nouveau rapidement vers des hautes altitudes. On va donc de nouveau tronquer le graphe afin de voir ce qui se passe dans les basses altitudes.
preemptifRedemarrage_tronquée <- function(lambdamin, lambdamax, stepLambda,
nloop) {
df <- mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "redemarrage",
"exp")
df <- rbind(df, mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "redemarrage",
"deter"))
df <- rbind(df, mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "redemarrage",
"unif"))
df <- rbind(df, mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "redemarrage",
"erlang0.5_2"))
df <- rbind(df, mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "redemarrage",
"erlang0.1_10"))
dfFinal <- ddply(df, c("Fonction", "Lambda"), summarize, Time = mean(R),
InterConfi = sd(R)/sqrt(length(R)))
ggplot(dfFinal, aes(x = Lambda, y = Time, ymin = Time - InterConfi, ymax = Time +
InterConfi, color = Fonction)) + geom_pointrange() + geom_errorbar() +
ylim(0, 50)
}
preemptifRedemarrage_tronquée(0.2, 0.8, 0.02, 10000)
## Warning: Removed 14 rows containing missing values (geom_segment).
## Warning: Removed 14 rows containing missing values (geom_point).
## Warning: Removed 6 rows containing missing values (geom_segment).
## Warning: Removed 6 rows containing missing values (geom_point).
## Warning: Removed 7 rows containing missing values (geom_segment).
## Warning: Removed 7 rows containing missing values (geom_point).
## Warning: Removed 20 rows containing missing values (geom_segment).
## Warning: Removed 20 rows containing missing values (geom_point).
## Warning: Removed 30 rows containing missing values (geom_segment).
## Warning: Removed 30 rows containing missing values (geom_point).
On remarque que de nouveau les lois déterministe et uniforme sont les plus stables, même si elles finissent par décolées vers la valeur lambda de 0.6.
Version avec réinitialisation
preemptifReinit(0.2, 0.8, 0.02, 1000)
Cette fois ce sont les lois uniformes et déterministes qui sont la cause des écrasements des autres courbes. On va donc de nouveau tronquer.
preemptifReinit_tronquée <- function(lambdamin, lambdamax, stepLambda, nloop) {
df <- mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "reinit", "exp")
df <- rbind(df, mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "reinit",
"deter"))
df <- rbind(df, mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "reinit",
"unif"))
df <- rbind(df, mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "reinit",
"erlang0.5_2"))
df <- rbind(df, mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "reinit",
"erlang0.1_10"))
dfFinal <- ddply(df, c("Fonction", "Lambda"), summarize, Time = mean(R),
InterConfi = sd(R)/sqrt(length(R)))
ggplot(dfFinal, aes(x = Lambda, y = Time, ymin = Time - InterConfi, ymax = Time +
InterConfi, color = Fonction)) + geom_pointrange() + geom_errorbar() +
ylim(0, 10)
}
preemptifReinit_tronquée(0.2, 0.8, 0.02, 10000)
## Warning: Removed 9 rows containing missing values (geom_segment).
## Warning: Removed 8 rows containing missing values (geom_point).
## Warning: Removed 7 rows containing missing values (geom_segment).
## Warning: Removed 6 rows containing missing values (geom_point).
## Warning: Removed 4 rows containing missing values (geom_path).
## Warning: Removed 4 rows containing missing values (geom_path).
Comme on le voyait précédemment, c'est étonnament la dernière loi gamma qui est extrèmement stable voir qui décroit en fonction de lambda. Peut être qu'il y a un problème ici ce serait bizarre que plus il y a de requêtes plus le serveur les traite rapidement mais on ne sait pas trop où se trouve l'erreur.
On va maintenant comparer les meilleurs lois des différents modes préemptifs.
preemptifSelectionDesLois <- function(lambdamin, lambdamax, stepLambda, nloop) {
df <- mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "reprise",
"exp")
df <- rbind(df, mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "redemarrage",
"unif"))
df <- rbind(df, mainPreemptif(lambdamin, lambdamax, stepLambda, nloop, "reinit",
"erlang0.1_10"))
dfFinal <- ddply(df, c("Fonction", "Lambda"), summarize, Time = mean(R),
InterConfi = sd(R)/sqrt(length(R)))
ggplot(dfFinal, aes(x = Lambda, y = Time, ymin = Time - InterConfi, ymax = Time +
InterConfi, color = Fonction)) + geom_pointrange() + geom_errorbar()
}
preemptifSelectionDesLois(0.2, 0.8, 0.02, 1000)
Comme on pouvait s'y attendre en traçant l'avant dernière courbe c'est toujours la dernière loi gamma qui remporte haut la main le temps de réponse du serveur le plus faible . Il n'est par ailleurs pas la peine de comparer cette courbe avec le mode non_préemptif, on sait d'avance qu'elle sera également la meilleure même si cela reste tout de même très bizarre. Peut être que le théorème sur les variances de service dans une liste fifo pourrait s'appliquer ici également ce qui expliquerait qu'elle soit du coup si stable.
Nous avons dit en guise de conclusion : “le temps de réponse d'une file FIFO M/G/1 ne dépend que du débit d'arrivée λ, du débit de service μ et de la variance du service”,
il n'est pas certains qu'on puisse dire la même chose pour les listes LIFO, même si cela pourrait expliquer le cas atypique de la loi de erlang qu'on a évoqué à la question précédente.
Enfin d'un point de vu pûrement “physique”, on remarque qu'à quelques exceptions près, l'utilisation d'une liste LIFO fait grimper les temps de réponse assez rapidement.