Поделиться через


Производительность сетевых драйверов

Минимизация длины пути отправки и получения

Хотя пути отправки и получения отличаются от драйвера к драйверу, существуют некоторые общие правила оптимизации производительности:

  • Оптимизация для общих путей. Средство Kernprof.exe предоставляется вместе с сборками Разработчика и IDW Windows, которые извлекают необходимые сведения. Разработчик должен рассмотреть подпрограммы, которые используют больше всего циклов ЦП, и попытаться уменьшить частоту вызова этих подпрограмм или время, затрачиваемое на эти подпрограммы.

  • Сократите время, затрачиваемое на DPC, чтобы драйвер сетевого адаптера не использовал избыточные системные ресурсы, что приведет к снижению общей производительности системы.

  • Убедитесь, что код отладки не скомпилирован в окончательную выпущенную версию драйвера; это позволяет избежать выполнения избыточного кода.

Секционирование данных и кода для минимизации общего доступа между процессорами

Секционирование необходимо, чтобы свести к минимуму общие данные и код между процессорами. Секционирование помогает сократить использование системной шины и повысить эффективность кэша процессора. Чтобы свести к минимуму общий доступ, средства записи драйверов должны учитывать следующее:

  • Реализуйте драйвер в качестве десериализованного мини-порта, как описано в разделе Десериализованные драйверы NDIS Miniport Drivers.

  • Используйте структуры данных для каждого процессора, чтобы сократить глобальный и общий доступ к данным. Это позволяет хранить статистические счетчики без синхронизации, что сокращает длину пути к коду и повышает производительность. Для жизненно важной статистики необходимо иметь счетчики для каждого процессора, которые добавляются вместе во время запроса. Если требуется глобальный счетчик, используйте операции с блокировкой, а не спин-блокировки для управления счетчиком. Сведения о том, как избежать использования спиновых блокировок, см. в разделе Правильное использование механизмов блокировки ниже.

    Для упрощения этого можно использовать KeGetCurrentProcessorNumberEx для определения текущего процессора. Чтобы определить количество процессоров при выделении структур данных для каждого процессора, можно использовать KeQueryGroupAffinity .

    Общее число битов, заданное в маске сходства, указывает количество активных процессоров в системе. Драйверы не должны предполагать, что все заданные биты в маске будут непрерывными, так как процессоры могут не быть последовательно нумерованы в будущих выпусках операционной системы. Число процессоров на компьютере SMP является отсчитываемое от нуля значение.

    Если драйвер хранит данные для каждого процессора, можно использовать функцию KeQueryGroupAffinity , чтобы уменьшить количество состязаний за строки кэша.

Предотвращение ложного общего доступа

Ложный общий доступ возникает, когда обработчики запрашивают общие переменные, независимые друг от друга. Однако поскольку переменные находятся в одной строке кэша, они совместно используются между процессорами. В таких ситуациях линия кэша будет перемещаться между процессорами для каждого доступа к любой из переменных в ней, что приводит к увеличению очистки и перезагрузки кэша. Это увеличивает использование системной шины и снижает общую производительность системы.

Чтобы избежать ложного совместного использования, с помощью NdisGetSharedDataAlignment с помощью NdisGetSharedDataAlignment выравнивайте важные структуры данных (например, спин-блокировки, заголовки буферных очередей, списки, по отдельности связанные списки).

Правильное использование механизмов блокировки

При неправильном использовании спин-блокировки могут снизить производительность. Драйверы должны свести к минимуму использование спин-блокировок, используя операции с блокировкой, где это возможно. Однако в некоторых случаях для некоторых целей лучше всего выбрать спин-блокировку. Например, если драйвер получает блокировку спина при обработке количества ссылок для количества пакетов, которые не были указаны обратно драйверу, нет необходимости использовать операцию с блокировкой. Дополнительные сведения см. в разделе Синхронизация и уведомления в сетевых драйверах.

Ниже приведены некоторые советы по эффективному использованию механизмов блокировки.

  • Для управления пулами ресурсов используйте функции списков с по отдельности NDIS, например следующие:

    NdisInitializeSListHead

    NdisInterlockedPushEntrySList

    NdisInterlockedPopEntrySList

    NdisQueryDepthSList

  • Если вам нужно использовать блокировки спина, используйте их только для защиты данных, а не кода. Не используйте одну блокировку для защиты всех данных, используемых в общих путях. Например, разделите данные, используемые в путях отправки и получения, на две структуры данных, чтобы, когда путь отправки должен заблокировать свои данные, путь получения не затрагивается.

  • Если вы используете блокировки спина и путь уже находится на уровне DPC, используйте функции NdisDprAcquireSpinLock и NdisDprReleaseSpinLock , чтобы избежать дополнительного кода при получении и освобождении блокировок.

  • Чтобы свести к минимуму количество операций получения и освобождения спин-блокировки, используйте следующие функции NDIS RWLock:

    NdisAllocateRWLock

    NdisAcquireRWLockRead

    NdisAcquireRWLockWrite

    NdisReleaseRWLock

Использование 64-разрядной версии DMA

64-разрядная версия DMA. Если сетевой адаптер поддерживает 64-разрядную версию DMA, необходимо выполнить действия, чтобы избежать дополнительных копий адресов, превышающих диапазон 4 ГБ. Когда драйвер вызывает NdisMRegisterScatterGatherDma, флаг NDIS_SG_DMA_64_BIT_ADDRESS должен быть задан в параметре Flags .

Обеспечение правильного выравнивания буфера

Выравнивание буфера на границе строки кэша повышает производительность при копировании данных из одного буфера в другой. Большинство буферов получения сетевых адаптеров правильно выравниваются при их первом выделении, но пользовательские данные, которые в конечном итоге должны быть скопированы в буфер приложения, не соответствуют выравниванию из-за занятого пространства заголовков. В случае данных TCP (наиболее распространенный сценарий) сдвиг из-за заголовков TCP, IP и Ethernet приводит к сдвигу 0x36 байтов. Чтобы устранить эту проблему, мы рекомендуем драйверам выделить немного больший буфер и вставить данные пакетов со смещением 0xA байтов. Это обеспечит правильное выравнивание пользовательских данных после сдвига буферов на 0x36 байтов заголовка. Дополнительные сведения о границах строк кэша см. в разделе Примечания для NdisMAllocateSharedMemory.

Использование Scatter-Gather DMA

NDIS Scatter/Gather DMA предоставляет оборудование с поддержкой передачи данных в несмежные диапазоны физической памяти и из него. Scatter-Gather DMA использует структуру SCATTER_GATHER_LIST , которая включает массив SCATTER_GATHER_ELEMENT структур и количество элементов в массиве. Эта структура извлекается из дескриптора пакетов, переданного в функцию отправки драйвера. Каждый элемент массива предоставляет длину и начальный физический адрес физической непрерывной Scatter-Gather области. Драйвер использует длину и адрес для передачи данных.

Использование Scatter-Gather подпрограмм для операций DMA может улучшить использование системных ресурсов, не блокируя эти ресурсы статически, как это было бы при использовании регистров карт. Дополнительные сведения см. в разделе NDIS Scatter/Gather DMA.

Если сетевой адаптер поддерживает разгрузку сегментации TCP (разгрузка большой отправки), драйверу потребуется передать максимальный размер буфера, который он может получить из TCP/IP, в параметр MaximumPhysicalMapping в функции NdisMRegisterScatterGatherDma . Это гарантирует, что драйвер имеет достаточно регистров карт для создания списка Scatter-Gather и устранения возможных выделений буферов и копирования. Дополнительные сведения см. в следующих статьях:

Поддержка регулирования на стороне получения

Чтобы свести к минимуму перебои во время воспроизведения мультимедиа в мультимедийных приложениях, драйверы NDIS 6.20 и более поздних версий должны поддерживать регулирование на стороне получения (RST) при обработке прерываний приема. Дополнительные сведения см. в разделе:

Регулирование на стороне получения в NDIS 6.20 "Пути к коду отправки и получения" в сводке изменений, необходимых для переноса драйвера miniport в NDIS 6.20