Informations de réglage DDS

Cette page fournit des conseils sur les ajustements de paramètres qui ont été trouvés pour résoudre les problèmes rencontrés lors de l’utilisation de diverses implémentations DDS sur Linux dans des situations réelles. Il est possible que les problèmes que nous avons identifiés sur Linux ou lors de l’utilisation d’un fournisseur se produisent pour d’autres plates-formes et fournisseurs non documentés ici.

Les recommandations ci-dessous sont des points de départ pour le réglage ; ils fonctionnaient pour des systèmes et des environnements spécifiques, mais le réglage peut varier en fonction d’un certain nombre de facteurs. Vous devrez peut-être augmenter ou diminuer les valeurs lors du débogage en fonction de facteurs tels que la taille des messages, la topologie du réseau, etc.

Il est important de reconnaître que les paramètres de réglage peuvent avoir un coût pour les ressources et peuvent affecter des parties de votre système au-delà de la portée des améliorations souhaitées. Les avantages de l’amélioration de la fiabilité doivent être mis en balance avec les inconvénients pour chaque cas individuel.

Réglage multi-fournisseurs

Problème : L’envoi de données via des connexions avec perte (généralement Wi-Fi) devient problématique lorsque certains fragments IP sont supprimés, ce qui peut entraîner la saturation de la mémoire tampon du noyau côté réception.

Lorsqu’il manque au moins un fragment IP à un paquet UDP, le reste des fragments reçus remplit la mémoire tampon du noyau. Par défaut, le noyau Linux expirera après 30 secondes d’essais de recombinaison de fragments de paquets. Étant donné que le tampon du noyau est plein à ce stade (la taille par défaut est de 256 Ko), aucun nouveau fragment ne peut entrer, et la connexion semblera donc « se bloquer » pendant de longues périodes.

Ce problème est générique pour tous les fournisseurs de DDS, les solutions impliquent donc l’ajustement des paramètres du noyau.

Solution : Utilisez des paramètres de qualité de service au mieux plutôt que des paramètres fiables.

Les paramètres de meilleur effort réduisent la quantité de trafic réseau puisque l’implémentation DDS n’a pas à supporter la surcharge de communications fiables, où les éditeurs exigent des accusés de réception pour les messages envoyés aux abonnés et doivent renvoyer les échantillons qui n’ont pas été correctement reçus.

Si le tampon du noyau pour les fragments IP est plein, le symptôme est toujours le même (blocage pendant 30 secondes). Cette solution devrait améliorer quelque peu le problème sans avoir à ajuster les paramètres.

Solution : Réduisez la valeur du paramètre ipfrag_time.

net.ipv4.ipfrag_time / /proc/sys/net/ipv4/ipfrag_time (défaut 30s) : Temps en secondes pour garder un fragment IP en mémoire.

Réduisez la valeur, par exemple, à 3s, en exécutant :

sudo sysctl net.ipv4.ipfrag_time=3

La réduction de la valeur de ce paramètre réduit également la fenêtre de temps où aucun fragment n’est reçu. Le paramètre est global pour tous les fragments entrants, de sorte que la possibilité de réduire sa valeur doit être envisagée pour chaque environnement.

Solution : Augmentez la valeur du paramètre ipfrag_high_thresh.

net.ipv4.ipfrag_high_thresh / /proc/sys/net/ipv4/ipfrag_high_thresh (par défaut : 262144 octets) : mémoire maximale utilisée pour réassembler les fragments IP.

Augmentez la valeur, par exemple, à 128 Mo, en exécutant :

sudo sysctl net.ipv4.ipfrag_high_thresh=134217728     # (128 MB)

L’augmentation significative de la valeur de ce paramètre est une tentative pour s’assurer que la mémoire tampon ne soit jamais complètement pleine. Cependant, la valeur devrait probablement être significativement élevée pour contenir toutes les données reçues pendant la fenêtre temporelle de ipfrag_time, en supposant qu’il manque un fragment à chaque paquet UDP.

Problème : L’envoi de messages personnalisés avec de grands tableaux de taille variable de types non primitifs entraîne une surcharge de sérialisation/désérialisation élevée et une charge du processeur. Cela peut entraîner un blocage de l’éditeur en raison d’un temps excessif passé dans publish() et des outils comme ros2 topic hz sous-signalant la fréquence réelle des messages reçus. Notez que, par exemple, builtin_interfaces/Time est également considéré comme un type non primitif et entraînera une surcharge de sérialisation plus élevée. En raison de la surcharge de sérialisation accrue, une grave dégradation des performances peut être observée lors de la transition naïve des types de messages personnalisés de ROS 1 à ROS 2.

Solution : Utilisez plusieurs tableaux de primitives au lieu d’un seul tableau de types personnalisés, ou regroupez-les dans un tableau d’octets, comme par ex. dans les messages PointCloud2. Par exemple, au lieu de définir un message FooArray comme :

Foo[] my_large_array

avec Foo est défini comme :

uint64 foo_1
uint32 foo_2

Au lieu de cela, définissez FooArray comme :

uint64[] foo_1_array
uint32[] foo_2_array

Réglage RTPS rapide

Problème : Le RTPS rapide inonde le réseau de gros volumes de données ou de données publiées rapidement lorsqu’il fonctionne via le Wi-Fi.

Voir les solutions sous Réglage multi-fournisseurs.

Réglage Cyclone DDS

Problème : Cyclone DDS ne transmet pas les messages volumineux de manière fiable, malgré l’utilisation de paramètres fiables et le transfert via un réseau câblé.

Ce problème devrait être résolu bientôt. Jusque-là, nous avons trouvé la solution suivante (déboguée à l’aide de ce programme de test):

Solution : Augmentez la taille maximale du tampon de réception du noyau Linux et la taille minimale du tampon de réception du socket utilisées par Cyclone.

Ajustements à résoudre pour un message de 9Mo :

Définissez la taille maximale du tampon de réception, rmem_max, en exécutant :

sudo sysctl -w net.core.rmem_max=2147483647

Ou définissez-le de manière permanente en éditant le fichier /etc/sysctl.d/10-cyclone-max.conf pour qu’il contienne :

net.core.rmem_max=2147483647

Ensuite, pour définir la taille minimale du tampon de réception des sockets demandée par Cyclone, écrivez un fichier de configuration que Cyclone utilisera au démarrage, comme ceci :

<?xml version="1.0" encoding="UTF-8" ?>
<CycloneDDS xmlns="https://cdds.io/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://cdds.io/config
https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/master/etc/cyclonedds.xsd">
    <Domain id="any">
        <Internal>
            <MinimumSocketReceiveBufferSize>10MB</MinimumSocketReceiveBufferSize>
        </Internal>
    </Domain>
</CycloneDDS>

Ensuite, chaque fois que vous allez exécuter un nœud, définissez la variable d’environnement suivante :

CYCLONEDDS_URI=file:///absolute/path/to/config_file.xml

Réglage RTI Connect

Problème : Connext ne transmet pas les messages volumineux de manière fiable, malgré l’utilisation de paramètres fiables et le transfert via un réseau câblé.

Solution : Ce profil Connect QoS, ainsi que l’augmentation du paramètre rmem_max.

Définissez la taille maximale du tampon de réception, rmem_max, en exécutant :

sudo sysctl -w net.core.rmem_max=4194304

En ajustant net.core.rmem_max à 4 Mo dans le noyau Linux, le profil QoS peut produire un comportement vraiment fiable.

Il a été prouvé que cette configuration délivre des messages de manière fiable via SHMEM|UDPv4, et avec juste UDPv4 sur une seule machine. Une configuration multi-machines a également été testée avec rmem_max à 4 Mo et à 20 Mo (deux machines connectées à 1 Gbit/s d’Ethernet), sans perte de message et avec des délais de livraison moyens de 700 ms et 371 ms, respectivement.

Sans configurer le rmem_max du noyau, le même profil Connext QoS prenait jusqu’à 12 secondes pour que les données soient livrées. Cependant, il a toujours au moins réussi à terminer la livraison.

Solution : Utilisez le Profil Connect QoS sans ajuster rmem_max.

Le fichier ROS2TEST_QOS_PROFILES.xml a été configuré à l’aide de la documentation de RTI sur la configuration des contrôleurs de flux. Il dispose de contrôleurs de débit lent, moyen et rapide (vu dans le lien du profil Connext QoS).

Le contrôleur de débit moyen a produit les meilleurs résultats pour notre cas. Cependant, les contrôleurs devront toujours être réglés pour la machine/le réseau/l’environnement particulier dans lequel ils fonctionnent. Les contrôleurs de flux Connext peuvent être utilisés pour régler la bande passante et son agressivité pour l’envoi de données, bien qu’une fois la bande passante d’une configuration particulière est passé, les performances commenceront à chuter.