Partager via


Performances dans les pilotes réseau

Réduction de la longueur du chemin d’accès d’envoi et de réception

Bien que les chemins d’envoi et de réception diffèrent d’un pilote à l’autre, il existe des règles générales pour les optimisations des performances :

  • Optimisez pour les chemins d’accès courants. L’outil Kernprof.exe est fourni avec les builds développeur et IDW de Windows qui extrait les informations nécessaires. Le développeur doit examiner les routines qui consomment le plus de cycles de processeur et tenter de réduire la fréquence d’appel de ces routines ou le temps consacré à ces routines.

  • Réduisez le temps consacré à DPC afin que le pilote de carte réseau n’utilise pas trop de ressources système, ce qui entraînerait une baisse des performances globales du système.

  • Assurez-vous que le code de débogage n’est pas compilé dans la version finale publiée du pilote ; cela évite d’exécuter un excès de code.

Partitionnement des données et du code pour réduire le partage entre les processeurs

Le partitionnement est nécessaire pour réduire le code et les données partagées entre les processeurs. Le partitionnement permet de réduire l’utilisation du bus système et d’améliorer l’efficacité du cache du processeur. Pour réduire le partage, les rédacteurs de pilotes doivent prendre en compte les éléments suivants :

  • Implémentez le pilote en tant que miniport désérialisé, comme décrit dans Pilotes de miniport NDIS désérialisés.

  • Utilisez des structures de données par processeur pour réduire l’accès aux données globales et partagées. Cela vous permet de conserver les compteurs de statistiques sans synchronisation, ce qui réduit la longueur du chemin du code et augmente les performances. Pour les statistiques d’état vital, disposez de compteurs par processeur qui sont ajoutés ensemble au moment de la requête. Si vous devez disposer d’un compteur global, utilisez des opérations interblocées au lieu de verrous tournants pour manipuler le compteur. Consultez Utilisation correcte des mécanismes de verrouillage ci-dessous pour plus d’informations sur la façon d’éviter d’utiliser des verrous de rotation.

    Pour faciliter cela, KeGetCurrentProcessorNumberEx peut être utilisé pour déterminer le processeur actuel. Pour déterminer le nombre de processeurs lors de l’allocation de structures de données par processeur, KeQueryGroupAffinity peut être utilisé.

    Le nombre total de bits défini dans le masque d’affinité indique le nombre de processeurs actifs dans le système. Les pilotes ne doivent pas supposer que tous les bits définis dans le masque seront contigus, car les processeurs risquent de ne pas être numérotés consécutivement dans les versions futures du système d’exploitation. Le nombre de processeurs dans une machine SMP est une valeur de base zéro.

    Si votre pilote gère les données par processeur, vous pouvez utiliser la fonction KeQueryGroupAffinity pour réduire la contention de ligne de cache.

Éviter les faux partages

Un faux partage se produit lorsque les processeurs demandent des variables partagées indépendantes les unes des autres. Toutefois, étant donné que les variables se trouvent sur la même ligne de cache, elles sont partagées entre les processeurs. Dans de telles situations, la ligne de cache se déplace entre les processeurs pour chaque accès à l’une des variables qu’elle contient, ce qui entraîne une augmentation des vidages et des rechargements du cache. Cela augmente l’utilisation du bus système et réduit les performances globales du système.

Pour éviter les faux partages, alignez les structures de données importantes (telles que les verrous de rotation, les en-têtes de file d’attente de mémoire tampon, les listes liées séparément) aux limites de ligne de cache à l’aide de NdisGetSharedDataAlignment.

Utilisation correcte des mécanismes de verrouillage

Les verrous de rotation peuvent réduire les performances s’ils ne sont pas utilisés correctement. Les pilotes doivent réduire leur utilisation des verrous de rotation en utilisant des opérations de verrouillage interblocage dans la mesure du possible. Toutefois, dans certains cas, un verrou tournant peut être le meilleur choix à certaines fins. Par exemple, si un pilote acquiert un verrou de rotation lors de la gestion du nombre de références pour le nombre de paquets qui n’ont pas été indiqués au pilote, il n’est pas nécessaire d’utiliser une opération interblocage. Pour plus d’informations, consultez Synchronisation et notification dans les pilotes réseau.

Voici quelques conseils pour utiliser efficacement les mécanismes de verrouillage :

  • Pour gérer les pools de ressources, utilisez des fonctions de liste liées séparément par NDIS, telles que les suivantes :

    NdisInitializesListHead

    NdisInterlockedPushEntrySList

    NdisInterlockedPopEntrySList

    NdisQueryDepthSList

  • Si vous avez besoin d’utiliser des verrous de rotation, utilisez-les uniquement pour protéger les données, et non le code. N’utilisez pas un seul verrou pour protéger toutes les données utilisées dans les chemins d’accès courants. Par exemple, séparez les données utilisées dans les chemins d’envoi et de réception en deux structures de données afin que lorsque le chemin d’envoi doit verrouiller ses données, le chemin de réception ne soit pas affecté.

  • Si vous utilisez des verrous de rotation et que le chemin est déjà au niveau DPC, utilisez les fonctions NdisDprAcquireSpinLock et NdisDprReleaseSpinLock pour éviter du code supplémentaire lors de l’acquisition et de la libération des verrous.

  • Pour réduire le nombre d’acquisitions et de mises en production de verrous de rotation, utilisez ces fonctions RWLock NDIS :

    NdisAllocateRWLock

    NdisAcquireRWLockRead

    NdisAcquireRWLockWrite

    NdisReleaseRWLock

Utilisation de DMA 64 bits

DMA 64 bits Si la carte réseau prend en charge DMA 64 bits, des étapes doivent être prises pour éviter des copies supplémentaires pour les adresses au-dessus de la plage de 4 Go. Lorsque le pilote appelle NdisMRegisterScatterGatherDma, l’indicateur NDIS_SG_DMA_64_BIT_ADDRESS doit être défini dans le paramètre Flags .

Garantir l’alignement correct de la mémoire tampon

L’alignement de la mémoire tampon sur une limite de ligne de cache améliore les performances lors de la copie de données d’une mémoire tampon vers une autre. La plupart des mémoires tampons de réception des cartes réseau sont correctement alignées lors de leur première allocation, mais les données utilisateur qui doivent finalement être copiées dans la mémoire tampon d’application sont mal alignées en raison de l’espace d’en-tête consommé. Dans le cas des données TCP (le scénario le plus courant), le décalage dû aux en-têtes TCP, IP et Ethernet entraîne un décalage de 0x36 octets. Pour résoudre ce problème, nous recommandons aux pilotes d’allouer une mémoire tampon légèrement plus grande et d’insérer des données de paquets à un décalage de 0xA octets. Cela garantit que, une fois que les mémoires tampons sont décalées de 0x36 octets pour l’en-tête, les données utilisateur sont correctement alignées. Pour plus d’informations sur les limites de ligne de cache, consultez la section Remarques pour NdisMAllocateSharedMemory.

Utilisation de Scatter-Gather DMA

NDIS Scatter/Collect DMA fournit au matériel la prise en charge du transfert de données vers et à partir de plages non incohérentes de mémoire physique. Scatter-Gather DMA utilise une structure SCATTER_GATHER_LIST , qui inclut un tableau de structures SCATTER_GATHER_ELEMENT et le nombre d’éléments dans le tableau. Cette structure est récupérée à partir du descripteur de paquets passé à la fonction d’envoi du pilote. Chaque élément du tableau fournit la longueur et l’adresse physique de départ d’une région Scatter-Gather contiguë physiquement. Le pilote utilise les informations de longueur et d’adresse pour transférer les données.

L’utilisation de la Scatter-Gather routines pour les opérations DMA peut améliorer l’utilisation des ressources système en ne verrouillant pas ces ressources de manière statique, comme cela se produirait si des registres cartographiques étaient utilisés. Pour plus d’informations, consultez NDIS Scatter/Collect DMA.

Si la carte réseau prend en charge le déchargement de segmentation TCP (déchargement d’envoi volumineux), le pilote doit passer la taille de mémoire tampon maximale qu’il peut obtenir à partir de TCP/IP dans le paramètre MaximumPhysicalMapping dans la fonction NdisMRegisterScatterGatherDma . Cela garantit que le pilote dispose de suffisamment de registres cartographiques pour générer la liste de Scatter-Gather et éliminer les allocations et la copie de mémoire tampon possibles. Pour plus d’informations, consultez les rubriques suivantes :

Prise en charge de la limitation côté réception

Pour réduire les interruptions lors de la lecture multimédia dans les applications multimédias, les pilotes NDIS 6.20 et ultérieur doivent prendre en charge la limitation côté réception (RST) dans le traitement des interruptions de réception. Pour plus d'informations, consultez les pages suivantes :

Limitation côté réception dans NDIS 6.20 « Chemins d’accès au code d’envoi et de réception » dans Résumé des modifications requises pour porter un pilote Miniport vers NDIS 6.20