Optimisation de la vitesse ADSL

Depuis que je me connecte à l'internet sous SUSE 10 en wifi en passant par ma Livebox Wanadoo, j'ai l'impression que cette connexion est plus lente que la même depuis un poste sous windows. Bizarre. Je vais regarder cela de plus près.

20 février 2006

J'installe côte à côte mon Gateway de bureau sous SUSE 10 (qui se connecte grâce au dongle de Wanadoo) et mon portable VAIO VGN-S3HP sous XP Pro (qui utilise sa carte wi-fi intégrée). Sur les deux, je lance Firefox (version 1.5.0.1 dans les deux cas). Dans les deux, j'ouvre dans deux onglets : d'une part, le site de mesure de 60 millions de consommateurs (avec le type de connexion "ADSL ou câble + 2 M (maxi 10M)" adapté à mon cas = abonnement Wanadoo 8 Mb/s) et, d'autre part, le site de mesure "audit my pc".

Quelques tests préliminaires montrent que ce dernier est plus optimiste que "60 millions" de 5 à 10%. Je sais par ailleurs que mon portable sous XP peut, aux heures favorables, dépasser légèrement 6 Mb/s en voie descendante ("download") et flirter avec 1 Mb/s en voie montante ("upload"). Aujourd'hui, en milieu de matinée, toutefois, les débits descendants fluctuent entre 3 et 4 Mb/s et les montants sont très stables à 800 Kb/s.

Pour ne pas risquer d'interférences, je lance un test sur une machine PUIS, tout de suite après, le même test sur l'autre, en changeant l'ordre de temps en temps. Après une dizaine de répétitions, il apparaît nettement que ma connexion Linux "tourne" à la moitié du débit obtenu sous XP. Il faut faire quelque chose pour optimiser les protocoles !

Après de patientes recherches, je trouve, sur le site de l'Université de Fordham (Bronx, NY), une page qui mentionne des variables importantes pour les performances du TCP et, sur le site du laboratoire national Lawrence Berkeley, une page qui donne un guide de réglage du TCP. Grâce aux noms de variables de ces pages, Google me trouve encore un document d'explication utile.

Armé de ces informations et de bonnes intentions, dans une console ouverte dans une session root, je fais :

# sysctl net

(faire "man sysctl" pour avoir le mode d'emploi de la commande sysctl) ; ceci produit une longue liste (6 pages) de paramètres dont voici un extrait :

net.ipv4.tcp_congestion_control = reno
net.ipv4.tcp_tso_win_divisor = 3
net.ipv4.tcp_moderate_rcvbuf = 1
net.ipv4.tcp_no_metrics_save = 0
net.ipv4.ipfrag_secret_interval = 600
net.ipv4.tcp_low_latency = 0
net.ipv4.tcp_frto = 0
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_adv_win_scale = 2
net.ipv4.tcp_app_win = 31
net.ipv4.tcp_rmem = 4096 87380 174760
net.ipv4.tcp_wmem = 4096 16384 131072
net.ipv4.tcp_mem = 12288 16384 24576
net.ipv4.tcp_dsack = 1
net.ipv4.tcp_ecn = 0
net.ipv4.tcp_reordering = 3
net.ipv4.tcp_fack = 1
net.ipv4.tcp_orphan_retries = 0
net.ipv4.tcp_max_syn_backlog = 1024
net.ipv4.tcp_rfc1337 = 0
net.ipv4.tcp_stdurg = 0
net.ipv4.tcp_abort_on_overflow = 0
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_fin_timeout = 60
net.ipv4.tcp_retries2 = 15
net.ipv4.tcp_retries1 = 3
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.ipfrag_time = 30
net.ipv4.ip_dynaddr = 0
net.ipv4.ipfrag_low_thresh = 196608
net.ipv4.ipfrag_high_thresh = 262144
net.ipv4.tcp_max_tw_buckets = 180000
net.ipv4.tcp_max_orphans = 4096
net.ipv4.tcp_synack_retries = 5
net.ipv4.tcp_syn_retries = 5
net.ipv4.tcp_retrans_collapse = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_timestamps = 1
net.core.rmem_default = 113664
net.core.wmem_default = 113664
net.core.rmem_max = 113664
net.core.wmem_max = 113664

Ces variables peuvent être changées dynamiquement (sans relance) avec la commande sysctl. Allons-y donc :

# sysctl -w net.core.rmem_max=524288

net.core.rmem_max = 524288

# sysctl -w net.core.wmem_max=524288

net.core.wmem_max = 524288

# sysctl net.core

net.core.netdev_budget = 300
net.core.somaxconn = 128
net.core.optmem_max = 10240
net.core.message_burst = 10
net.core.message_cost = 5
net.core.netdev_max_backlog = 1000
net.core.dev_weight = 64
net.core.rmem_default = 113664
net.core.wmem_default = 113664
net.core.rmem_max = 524288
net.core.wmem_max = 524288

Quelques tests de bande passante indiquent que ces modifications font progresser le débit significativement, en faisant gagner environ 50% de l'écart de performance. Passons aux autres variables :

# sysctl -w net.ipv4.tcp_keepalive_time=1800
# sysctl -w net.ipv4.tcp_fin_timeout=30
# sysctl -w net.ipv4.tcp_syn_retries=3

Ces modifications semblent apporter un mieux marginal.

Une tentative d'augmenter encore les tampons rmem_max et wmem_max montre qu'aller au-delà de 786432 ne fait pas gagner davantage d'avantage. J'applique donc :

# sysctl -w net.core.wmem_max=786432
# sysctl -w net.core.rmem_max=786432

Avec tout ça, SUSE n'est plus qu'à 20% derrière XP... Si j'en crois mes lectures, les valeurs par défaut des tampons ne doivent pas faire plus que 128K. Comme elles sont inférieures à cette valeur, je vais les pousser un peu :

# sysctl -w net.core.rmem_default=131072
# sysctl -w net.core.wmem_default=131072

Il semble que cela fasse gagner encore quelques %.
Tous comptes faits, en voie descendante, la connexion sous SUSE tourne maintenant environ 10 ou 15% moins vite que celle sous XP. C'est vrai que j'aimerais bien savoir pourquoi... mais je vais considérer que c'est satisfaisant. En revanche, les voies montantes font régulièrement jeu égal à 800 Kb/s.

21 février 2006

Je fais le test en rallumant mon ordinateur. Patatras, les débits sont retombés ! Les modifs ne sont pas permanentes.
Je trouve la solution sur http://l2.iap.fr/. Selon les indications de cette page, à l'aide de mon éditeur de texte (gedit), j'introduis ce qui suit dans le fichier etc/sysctl.conf :

# ===========================================
# Modifications suivantes le 21-2-6 pour optimiser internet
# increase Linux TCP buffer bytes size limits and defaults
net.core.rmem_max = 786432
net.core.wmem_max = 786432
net.core.rmem_default=131072
net.core.wmem_default=131072
# increase Linux autotuning TCP buffer limits
# min, default, and max number of bytes to use
net.ipv4.tcp_rmem = 4096 87380 786432
net.ipv4.tcp_wmem = 4096 65536 786432
# decrease waiting times
net.ipv4.tcp_keepalive_time = 1800
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_syn_retries = 3
# Fin des modifications le 21-2-6
# ===========================================

J'éteins, je rallume, cette fois c'est bon.
Petite remarque en passant, comparons les valeurs "optimales" (pour mon ordinateur) obtenues empiriquement aux valeurs théoriques que l'on trouve sur certains sites :

Tampon théorique en octets = (débit de la liaison en octets/s) * (RTT en s)

Le RTT (Round trip time) est le temps d'aller-retour affiché par un ping sur un serveur. Dans mon cas, en admettant que la liaison utilise 80% de la bande passante "promise" par mon FAI Wanadoo (soit envron 6 Mb/s) et que je peux prendre pour le RTT une valeur moyenne de 0,2 s (j'obtiens par des pings un éventail de 50 ms sur le site de mon FAI à plus de 400 ms sur des serveurs australiens) :

Tampon théorique en octets = 6 000 000 b/s * 0,2 s / 8 = 150 000 o.

Il ne semble donc pas incohérent d'avoir pris 128 Ko (=131072 o) comme valeur par défaut et 768 Ko (= 786432 o = 6 fois la valeur par défaut) comme valeur maximale, sachant que les performances sont quasiment identiques avec un facteur 4.

Voilà, j'ai tout ce qu'il faut pour récapituler mon astuce.


Retour à l'accueil LINUX