Rendimiento en controladores de red
- Minimizar la longitud de la ruta de acceso de envío y recepción
- Creación de particiones de datos y código para minimizar el uso compartido entre procesadores
- Evitar el uso compartido falso
- Uso de mecanismos de bloqueo correctamente
- Uso de DMA de 64 bits
- Garantizar la alineación correcta del búfer
- Uso de Scatter-Gather DMA
- Compatibilidad con la limitación lateral de recepción
Minimizar la longitud de la ruta de acceso de envío y recepción
Aunque las rutas de acceso de envío y recepción difieren del controlador al controlador, hay algunas reglas generales para las optimizaciones de rendimiento:
Optimice las rutas de acceso comunes. La herramienta Kernprof.exe se proporciona con las compilaciones para desarrolladores e IDW de Windows que extraen la información necesaria. El desarrollador debe examinar las rutinas que consumen la mayoría de los ciclos de CPU e intentar reducir la frecuencia de estas rutinas a las que se llama o el tiempo empleado en estas rutinas.
Reduzca el tiempo invertido en DPC para que el controlador del adaptador de red no use recursos del sistema excesivos, lo que provocaría que el rendimiento general del sistema sufra.
Asegúrese de que el código de depuración no se compila en la versión final del controlador; Esto evita la ejecución de un exceso de código.
Creación de particiones de datos y código para minimizar el uso compartido entre procesadores
La creación de particiones es necesaria para minimizar los datos compartidos y el código entre procesadores. La creación de particiones ayuda a reducir el uso del bus del sistema y mejora la eficacia de la memoria caché del procesador. Para minimizar el uso compartido, los escritores de controladores deben tener en cuenta lo siguiente:
Implemente el controlador como miniporte deserializado tal y como se describe en Controladores de miniporte NDIS deserializados.
Use estructuras de datos por procesador para reducir el acceso a datos globales y compartidos. Esto le permite mantener contadores estadísticos sin sincronización, lo que reduce la longitud de la ruta de acceso del código y aumenta el rendimiento. Para las estadísticas vitales, tiene contadores por procesador que se agregan juntos en el momento de la consulta. Si debe tener un contador global, use operaciones interbloqueadas en lugar de bloqueos de número para manipular el contador. Consulte Uso de mecanismos de bloqueo correctamente a continuación para obtener información sobre cómo evitar el uso de bloqueos de número.
Para facilitar esto, se puede usar KeGetCurrentProcessorNumberEx para determinar el procesador actual. Para determinar el número de procesadores al asignar estructuras de datos por procesador, se puede usar KeQueryGroupAffinity .
El número total de bits establecidos en la máscara de afinidad indica el número de procesadores activos en el sistema. Los controladores no deben suponer que todos los bits establecidos de la máscara serán contiguos porque es posible que los procesadores no se numeran consecutivamente en las futuras versiones del sistema operativo. El número de procesadores de una máquina SMP es un valor de base cero.
Si el controlador mantiene los datos por procesador, puede usar la función KeQueryGroupAffinity para reducir la contención de la línea de caché.
Evitar el uso compartido falso
El uso compartido falso se produce cuando los procesadores solicitan variables compartidas independientes entre sí. Sin embargo, dado que las variables están en la misma línea de caché, se comparten entre los procesadores. En tales situaciones, la línea de caché se desplazará de nuevo y hacia delante entre los procesadores para cada acceso a cualquiera de las variables de ella, lo que provocará un aumento en los vaciados y recargas de caché. Esto aumenta el uso del bus del sistema y reduce el rendimiento general del sistema.
Para evitar el uso compartido falso, alinee estructuras de datos importantes (como bloqueos de número, encabezados de cola de búfer, listas vinculadas de forma singly) a límites de línea de caché mediante NdisGetSharedDataAlignment.
Uso de mecanismos de bloqueo correctamente
Los bloqueos de número pueden reducir el rendimiento si no se usan correctamente. Los controladores deben minimizar el uso de bloqueos de giro mediante operaciones interbloqueadas siempre que sea posible. Sin embargo, en algunos casos, un bloqueo de número podría ser la mejor opción para algunos propósitos. Por ejemplo, si un controlador adquiere un bloqueo de giro mientras controla el recuento de referencias para el número de paquetes que no se han indicado de vuelta al controlador, no es necesario usar una operación interbloqueada. Para obtener más información, consulte Sincronización y notificación en controladores de red.
Estas son algunas sugerencias para usar mecanismos de bloqueo de forma eficaz:
Use funciones de lista vinculadas de NDIS como las siguientes para administrar grupos de recursos:
Si necesita usar bloqueos de número, úselos solo para proteger los datos, no para el código. No use un bloqueo para proteger todos los datos usados en rutas de acceso comunes. Por ejemplo, separe los datos usados en las rutas de acceso de envío y recepción en dos estructuras de datos para que cuando la ruta de acceso de envío necesite bloquear sus datos, la ruta de acceso de recepción no se ve afectada.
Si usa bloqueos de número y la ruta de acceso ya está en el nivel DPC, use las funciones NdisDprAcquireSpinLock y NdisDprReleaseSpinLock para evitar código adicional al adquirir y liberar los bloqueos.
Para minimizar el número de adquisición y liberación del bloqueo de número, use estas funciones RWLock de NDIS:
Uso de DMA de 64 bits
DMA de 64 bits Si el adaptador de red admite DMA de 64 bits, se deben realizar pasos para evitar copias adicionales para direcciones por encima del intervalo de 4 GB. Cuando el controlador llama a NdisMRegisterScatterGatherDma, la marca NDIS_SG_DMA_64_BIT_ADDRESS debe establecerse en el parámetro Flags .
Garantizar la alineación correcta del búfer
La alineación del búfer en un límite de línea de caché mejora el rendimiento al copiar datos de un búfer a otro. La mayoría de los búferes de recepción del adaptador de red se alinean correctamente cuando se asignan por primera vez, pero los datos de usuario que finalmente deben copiarse en el búfer de la aplicación se desalinean debido al espacio de encabezado consumido. En el caso de los datos TCP (el escenario más común), el cambio debido a los encabezados TCP, IP y Ethernet da como resultado un desplazamiento de 0x36 bytes. Para resolver este problema, se recomienda que los controladores asignen un búfer ligeramente mayor e inserten datos de paquetes en un desplazamiento de 0xA bytes. Esto garantizará que, después de que los búferes se cambien por 0x36 bytes para el encabezado, los datos del usuario se alinean correctamente. Para obtener más información sobre los límites de la línea de caché, vea la sección Comentarios de NdisMAllocateSharedMemory.
Uso de Scatter-Gather DMA
NDIS Scatter/Gather DMA proporciona compatibilidad con el hardware para transferir datos hacia y desde intervalos no contiguos de memoria física. Scatter-Gather DMA usa una estructura SCATTER_GATHER_LIST , que incluye una matriz de estructuras de SCATTER_GATHER_ELEMENT y el número de elementos de la matriz. Esta estructura se recupera del descriptor de paquetes que se pasa a la función de envío del controlador. Cada elemento de la matriz proporciona la longitud y la dirección física inicial de una región de Scatter-Gather físicamente contigua. El controlador usa la información de longitud y dirección para transferir los datos.
El uso de las rutinas de Scatter-Gather para las operaciones DMA puede mejorar el uso de los recursos del sistema al no bloquear estos recursos estáticamente, como ocurriría si se usaran registros de mapa. Para obtener más información, consulte Dispersión y recopilación de DMA de NDIS.
Si el adaptador de red admite la descarga de segmentación TCP (descarga de envío grande), el controlador tendrá que pasar el tamaño máximo del búfer que puede obtener de TCP/IP al parámetro MaximumPhysicalMapping dentro de la función NdisMRegisterScatterGatherDma . Esto garantizará que el controlador tenga suficientes registros de mapa para compilar la lista de Scatter-Gather y eliminar las posibles asignaciones de búfer y copiar. Para más información, consulte los temas siguientes:
- Determinar las funcionalidades de descarga de tareas
- Descarga de la segmentación de paquetes TCP grandes
Compatibilidad con la limitación lateral de recepción
Para minimizar las interrupciones durante la reproducción multimedia en aplicaciones multimedia, los controladores NDIS 6.20 y posteriores deben admitir la limitación lateral de recepción (RST) en el procesamiento de interrupciones de recepción. Para más información, consulte:
Limitación lateral de recepción en NDIS 6.20 "Rutas de acceso de código de envío y recepción" en Resumen de los cambios necesarios para migrar un controlador de miniporte a NDIS 6.20