--- title: "Estimation de la latence et de la capacité d’une connexion à partir de mesures asymétriques" author: "Louis Le Nézet" output: pdf_document: toc: true html_document: toc: true theme: journal documentclass: article classoption: a4paper header-includes: - \usepackage[french]{babel} - \usepackage[upright]{fourier} - \hypersetup{colorlinks=true,pagebackref=true} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE) ``` ## Problématique Un modèle simple et fréquemment utilisé pour décrire la performance d'une connexion de réseau consiste à supposer que le temps d'envoi T pour un message dépend principalement de sa taille S (nombre d'octets) et de deux grandeurs propres à la connexion : la latence L (en secondes) et la capacité C (en octets/seconde). La relation entre ces quatre quantités est T(S) = L + S/C. Ce modèle néglige un grand nombre de détails. D'une part, L et C dépendent bien sûr du protocole de communication choisi mais aussi dans une certaine mesure de S. D'autre part, la mesure de T(S) comporte en général une forte composante aléatoire. Nous nous intéressons ici au temps moyen qu'il faut pour envoyer un message d'une taille donnée. ## Objectif Nous souhaitons ici estimer L et C à partir d'une série d'observations de T pour des valeurs différentes de S. ## Préparation des données 1) Le premier jeu de données examine une connexion courte à l'intérieur d'un campus disponible [ici](http://mescal.imag.fr/membres/arnaud.legrand/teaching/2014/RICM4_EP_ping/liglab2.log.gz) L'URL est: ```{r} data_url1 = "http://mescal.imag.fr/membres/arnaud.legrand/teaching/2014/RICM4_EP_ping/liglab2.log.gz" ``` Pour nous protéger contre une éventuelle disparition ou modification du serveur du site, nous faisons une copie locale de ce jeux de données que nous préservons avec notre analyse. Il est inutile et même risquée de télécharger les données à chaque exécution, car dans le cas d'une panne nous pourrions remplacer nos données par un fichier défectueux. Pour cette raison, nous téléchargeons les données seulement si la copie locale n'existe pas. ```{r} data_file_gz = "liglab2.log.gz" if (!file.exists(data_file_gz)) { download.file(data_url1, data_file, method="auto") } ``` Il faut ensuite charger les données dans un objet R ```{r} liglab2 <- read.table(data_file, header=FALSE, sep=";") ``` Il va falloir désormais séparer les données en fonction de leur emplacement. Les données sont pour l'instant en format string. Au début, entre crochet, vous trouvez la date à laquelle la mesure a été prise, exprimée en secondes depuis le 1er janvier 1970. La taille du message en octets est donnée juste après, suivie par le nom de la machine cible et son adresse IP, qui sont normalement identiques pour toutes les lignes à l'intérieur d'un jeu de données. À la fin de la ligne, nous trouvons le temps d'envoi (aller-retour) en millisecondes. Les autres indications, icmp_seq et ttl, n'ont pas d'importance pour notre analyse. Attention, il peut arriver qu'une ligne soit incomplète et il faut donc vérifier chaque ligne avant d'en extraire des informations ! Ici est écris la fonction qui sépare tout d'abord les données. Puis extrait les données nécessaire en les mettant dans une liste ```{r} require(stringr) extract_infos <- function(x){ infos = str_split(x," ") infos = str_remove_all(infos[[1]],"\\[|\\]|\\(|\\)|:") data=list() data["date_ms"] = as.numeric(infos[1]) data["size"] = as.integer(infos[2]) data["ip"] = infos[6] if (any(str_detect(infos,"time="))){ data["time"] = as.integer(str_remove(infos[str_detect(infos,"time=")],"time=")) }else{ data["time"] = NA } return(data) } ``` We need now to apply this function on the whole data and use it as a dataframe ```{r} library(data.table) df = rbindlist(lapply(liglab2$V1, extract_infos)) ``` Pour la gestion de date nous allons utiliser la librairie parsedate ```{r} df$date=as.POSIXct(df$date_ms,origin='1970-01-01 00:00') summary(df) ``` ```{r} library(ggplot2) ggplot(df,aes(x=date,time))+ geom_point() ggplot(head(df,200),aes(x=date,time))+ geom_point() ggplot(tail(df,200),aes(x=date,time))+ geom_point() ``` A première vue il semble y avoir une différence de temps à partir de 1480 bytes. ```{r} library(ggplot2) ggplot(df,aes(x=size,time))+ geom_point() ggplot(df[df$size>1450 & df$size<1500,],aes(x=size,time))+ geom_point() ``` On crée donc deux classe ```{r} df$class = cut(df$size,breaks = c(0,1480,2020), labels=c("small", "big")) ``` Et on peut représenter désormais l'impact en fonction de la taille et de la class sur le temps ```{r} library(ggpmisc) ggplot(df, aes(x=size, y=time, colour=class))+ stat_poly_line() + stat_poly_eq(aes(label = paste(after_stat(eq.label), after_stat(rr.label), sep = "*\", \"*"))) + geom_point() ``` La variabilité est tellement forte et asymétrique que la régression du temps moyen peut être considérée comme peu pertinente. On peut vouloir s'intéresser à caractériser plutôt le plus petit temps de transmission. Une approche possible consiste donc à filtrer le plus petit temps de transmission pour chaque taille de message et à effectuer la régression sur ce sous-ensemble de données. ```{r} library(quantreg) modelSmall <- rq(time ~ size , data = df[df$class=="small",], tau = 0.1) summary(modelSmall, se = "iid") modelBig <- rq(time ~ size , data = df[df$class=="big",], tau = 0.1) summary(modelBig, se = "iid") ``` Avec cette analyse on remarque que la latence pour le premier quantile est de 1 seconde pour les petits paquets et de 2 secondes pour les gros. La capacité de connexion est aussi différente 0.00049 pour les petits et 0.00632 pour les gros. Il est possible de refaire cette analyse avec l'autre jeux de données disponible [ici](http://mescal.imag.fr/membres/arnaud.legrand/teaching/2014/RICM4_EP_ping/stackoverflow.log.gz) En changeant simplement l'url par celle-ci http://mescal.imag.fr/membres/arnaud.legrand/teaching/2014/RICM4_EP_ping/stackoverflow.log.gz