Condividi tramite


Prestazioni nei driver di rete

Riduzione della lunghezza del percorso di invio e ricezione

Anche se i percorsi di invio e ricezione differiscono dal driver al driver, esistono alcune regole generali per le ottimizzazioni delle prestazioni:

  • Ottimizzare per i percorsi comuni. Lo strumento Kernprof.exe viene fornito con le build developer e IDW di Windows che estraggono le informazioni necessarie. Lo sviluppatore deve esaminare le routine che utilizzano la maggior parte dei cicli della CPU e tentare di ridurre la frequenza di chiamata di queste routine o il tempo impiegato in queste routine.

  • Ridurre il tempo impiegato in DPC in modo che il driver della scheda di rete non usi risorse di sistema eccessive, il che provocherebbe un sovraccarico delle prestazioni complessive del sistema.

  • Assicurarsi che il codice di debug non venga compilato nella versione finale rilasciata del driver; in questo modo si evita l'esecuzione di codice in eccesso.

Partizionamento dei dati e del codice per ridurre al minimo la condivisione tra processori

Il partizionamento è necessario per ridurre al minimo i dati condivisi e il codice tra processori. Il partizionamento consente di ridurre l'utilizzo del bus di sistema e di migliorare l'efficacia della cache del processore. Per ridurre al minimo la condivisione, i writer di driver devono considerare quanto segue:

  • Implementare il driver come miniport deserializzato come descritto in Driver miniport NDIS deserializzati.

  • Usare strutture di dati per processore per ridurre l'accesso ai dati globali e condivisi. In questo modo è possibile mantenere i contatori delle statistiche senza sincronizzazione, riducendo la lunghezza del percorso del codice e aumentando le prestazioni. Per le statistiche vitali, sono presenti contatori per processore che vengono aggiunti insieme in fase di query. Se è necessario disporre di un contatore globale, utilizzare operazioni interlocked anziché blocchi di selezione per modificare il contatore. Per informazioni su come evitare l'uso di blocchi di rotazione, vedere Uso dei meccanismi di blocco.

    Per facilitare questa operazione, è possibile usare KeGetCurrentProcessorNumberEx per determinare il processore corrente. Per determinare il numero di processori durante l'allocazione di strutture di dati per processore, è possibile usare KeQueryGroupAffinity .

    Il numero totale di bit impostati nella maschera di affinità indica il numero di processori attivi nel sistema. I driver non devono presupporre che tutti i bit impostati nella maschera saranno contigui perché i processori potrebbero non essere numerati consecutivamente nelle versioni future del sistema operativo. Il numero di processori in un computer SMP è un valore in base zero.

    Se il driver gestisce i dati per processore, è possibile usare la funzione KeQueryGroupAffinity per ridurre la contesa della riga di cache.

Evitare la condivisione falsa

La condivisione false si verifica quando i processori richiedono variabili condivise indipendenti l'una dall'altra. Tuttavia, poiché le variabili si trovano nella stessa riga della cache, vengono condivise tra i processori. In tali situazioni, la riga della cache viaggia avanti e indietro tra processori per ogni accesso a una qualsiasi delle variabili in esso contenute, causando un aumento degli scaricamenti della cache e ricaricamenti. Ciò aumenta l'utilizzo del bus di sistema e riduce le prestazioni complessive del sistema.

Per evitare la condivisione falsa, allineare strutture di dati importanti (ad esempio blocchi di selezione, intestazioni della coda di buffer, elenchi collegati in modo automatico) ai limiti della riga della cache usando NdisGetSharedDataAlignment.

Uso corretto dei meccanismi di blocco

I blocchi di rotazione possono ridurre le prestazioni se non vengono usati correttamente. I driver devono ridurre al minimo l'uso dei blocchi di rotazione usando le operazioni interlocked laddove possibile. Tuttavia, in alcuni casi, un blocco di rotazione potrebbe essere la scelta migliore per alcuni scopi. Ad esempio, se un driver acquisisce un blocco di rotazione durante la gestione del conteggio dei riferimenti per il numero di pacchetti che non sono stati indicati di nuovo al driver, non è necessario utilizzare un'operazione interlocked. Per altre informazioni, vedere Sincronizzazione e notifica nei driver di rete.

Ecco alcuni suggerimenti per l'uso efficace dei meccanismi di blocco:

Uso di DMA a 64 bit

DMA a 64 bit Se la scheda di rete supporta DMA a 64 bit, è necessario eseguire passaggi per evitare copie aggiuntive per gli indirizzi superiori all'intervallo di 4 GB. Quando il driver chiama NdisMRegisterScatterGatherDma, il flag NDIS_SG_DMA_64_BIT_ADDRESS deve essere impostato nel parametro Flags .

Garantire l'allineamento corretto del buffer

L'allineamento del buffer su un limite di riga della cache migliora le prestazioni durante la copia dei dati da un buffer a un altro. La maggior parte dei buffer di ricezione della scheda di rete è allineata correttamente quando vengono allocate per la prima volta, ma i dati utente che alla fine devono essere copiati nel buffer dell'applicazione non sono allineati a causa dello spazio di intestazione utilizzato. Nel caso dei dati TCP (scenario più comune), lo spostamento dovuto alle intestazioni TCP, IP e Ethernet comporta uno spostamento di 0x36 byte. Per risolvere questo problema, è consigliabile che i driver allocano un buffer leggermente più grande e inseriscano i dati dei pacchetti in corrispondenza di un offset di 0xA byte. In questo modo, dopo che i buffer vengono spostati di 0x36 byte per l'intestazione, i dati utente sono allineati correttamente. Per altre informazioni sui limiti della riga di cache, vedere la sezione Osservazioni per NdisMAllocateSharedMemory.

Uso di Scatter-Gather DMA

NDIS Scatter/Gather DMA fornisce l'hardware con supporto per trasferire i dati da e verso intervalli non contigui di memoria fisica. Scatter-Gather DMA usa una struttura SCATTER_GATHER_LIST , che include una matrice di strutture SCATTER_GATHER_ELEMENT e il numero di elementi nella matrice. Questa struttura viene recuperata dal descrittore di pacchetti passato alla funzione di invio del driver. Ogni elemento della matrice fornisce la lunghezza e l'indirizzo fisico iniziale di un'area Scatter-Gather fisicamente contigua. Il driver usa le informazioni sulla lunghezza e sull'indirizzo per il trasferimento dei dati.

L'uso delle routine di Scatter-Gather per le operazioni DMA può migliorare l'utilizzo delle risorse di sistema non bloccando queste risorse in modo statico, come avviene se fossero stati usati registri mappa. Per altre informazioni, vedere NDIS Scatter/Gather DMA.

Se la scheda di rete supporta l'offload segmentazione TCP (Offload di invio di grandi dimensioni), il driver dovrà passare le dimensioni massime del buffer che può ottenere da TCP/IP nel parametro MaximumPhysicalMapping all'interno della funzione NdisMRegisterScatterGatherDma . Ciò garantisce che il driver disponga di registri mappa sufficienti per compilare l'elenco di Scatter-Gather ed eliminare eventuali allocazioni e copia del buffer possibili. Per altre informazioni, vedere gli argomenti seguenti:

Supporto della limitazione lato ricezione

Per ridurre al minimo le interruzioni durante la riproduzione multimediale nelle applicazioni multimediali, i driver NDIS 6.20 e versioni successive devono supportare Receive Side Throttle (RST) durante l'elaborazione di interrupt. Per altre informazioni, vedere:

Limitazione lato ricezione in NDIS 6.20 "Invia e ricevi percorsi di codice" in Riepilogo delle modifiche necessarie per convertire un driver Miniport a NDIS 6.20