다음을 통해 공유


네트워크 드라이버의 성능

송신 및 수신 경로 길이 최소화

송신 및 수신 경로는 드라이버와 드라이버 간에 다르지만 성능 최적화에 대한 몇 가지 일반적인 규칙이 있습니다.

  • 공통 경로에 최적화합니다. Kernprof.exe 도구는 필요한 정보를 추출하는 Windows의 개발자 및 IDW 빌드와 함께 제공됩니다. 개발자는 CPU 주기를 가장 많이 사용하는 루틴을 살펴보고 이러한 루틴이 호출되는 빈도 또는 이러한 루틴에 소요된 시간을 줄여야 합니다.

  • 네트워크 어댑터 드라이버가 과도한 시스템 리소스를 사용하지 않도록 DPC에서 소요된 시간을 줄여 전체 시스템 성능이 저하됩니다.

  • 디버깅 코드가 드라이버의 최종 릴리스 버전으로 컴파일되지 않았는지 확인합니다. 이렇게 하면 초과 코드가 실행되는 것을 방지할 수 있습니다.

데이터 및 코드를 분할하여 프로세서 간 공유 최소화

프로세서 간에 공유 데이터 및 코드를 최소화하려면 분할이 필요합니다. 분할은 시스템 버스 사용률을 줄이고 프로세서 캐시의 효율성을 개선하는 데 도움이 됩니다. 공유를 최소화하려면 드라이버 작성기에서 다음을 고려해야 합니다.

  • 역직렬화된 NDIS 미니포트 드라이버에 설명된 대로 드라이버를 역직렬화된 미니포트로 구현합니다.

  • 프로세서별 데이터 구조를 사용하여 전역 및 공유 데이터 액세스를 줄입니다. 이렇게 하면 동기화 없이 통계 카운터를 유지할 수 있으므로 코드 경로 길이가 줄어들고 성능이 향상됩니다. 중요한 통계의 경우 쿼리 시간에 함께 추가되는 프로세서별 카운터가 있습니다. 전역 카운터가 있어야 하는 경우 스핀 잠금 대신 연동 연산을 사용하여 카운터를 조작합니다. 스핀 잠금을 사용하지 않는 방법에 대한 자세한 내용은 아래의 잠금 메커니즘 사용을 참조하세요.

    이를 용이하게 하기 위해 KeGetCurrentProcessorNumberEx 를 사용하여 현재 프로세서를 확인할 수 있습니다. 프로세서별 데이터 구조를 할당할 때 프로세서 수를 확인하기 위해 KeQueryGroupAffinity 를 사용할 수 있습니다.

    선호도 마스크에 설정된 총 비트 수는 시스템의 활성 프로세서 수를 나타냅니다. 드라이버에서는 이후 운영 체제 릴리스에서 프로세서 번호가 연속적으로 지정되지 않을 수 있으므로 마스크의 모든 설정된 비트가 연속적으로 수행된다고 가정해서는 안 됩니다. SMP 컴퓨터의 프로세서 수는 0부터 시작하는 값입니다.

    드라이버가 프로세서별 데이터를 유지 관리하는 경우 KeQueryGroupAffinity 함수를 사용하여 캐시 라인 경합을 줄일 수 있습니다.

거짓 공유 방지

거짓 공유는 프로세서가 서로 독립적인 공유 변수를 요청할 때 발생합니다. 그러나 변수는 동일한 캐시 라인에 있으므로 프로세서 간에 공유됩니다. 이러한 경우 캐시 줄은 해당 변수에 액세스할 때마다 프로세서 사이를 오가며 캐시 플러시 및 다시 로드가 증가합니다. 이렇게 하면 시스템 버스 사용률이 증가하고 전체 시스템 성능이 저하됩니다.

거짓 공유를 방지하려면 NdisGetSharedDataAlignment를 사용하여 중요한 데이터 구조(예: 스핀 잠금, 버퍼 큐 헤더, 연결된 목록)를 캐시 라인 경계에 맞춥니다.

잠금 메커니즘을 올바르게 사용

스핀 잠금은 제대로 사용되지 않으면 성능을 저하시킬 수 있습니다. 드라이버는 가능한 한 연동된 연산을 사용하여 스핀 잠금 사용을 최소화해야 합니다. 그러나 경우에 따라 스핀 잠금이 어떤 목적에 가장 적합한 선택일 수 있습니다. 예를 들어 드라이버가 드라이버에 다시 표시되지 않은 패킷 수에 대한 참조 횟수를 처리하는 동안 스핀 잠금을 획득하는 경우 연동 작업을 사용할 필요가 없습니다. 자세한 내용은 네트워크 드라이버의 동기화 및 알림을 참조하세요.

다음은 잠금 메커니즘을 효과적으로 사용하기 위한 몇 가지 팁입니다.

64비트 DMA 사용

64비트 DMA 네트워크 어댑터가 64비트 DMA를 지원하는 경우 4GB 범위 이상의 주소에 대한 추가 복사본을 방지하려면 단계를 수행해야 합니다. 드라이버가 NdisMRegisterScatterGatherDma를 호출하는 경우 flags매개 변수 에서 NDIS_SG_DMA_64_BIT_ADDRESS 플래그를 설정해야 합니다.

적절한 버퍼 맞춤 확인

캐시 라인 경계의 버퍼 맞춤은 한 버퍼에서 다른 버퍼로 데이터를 복사할 때 성능을 향상시킵니다. 대부분의 네트워크 어댑터 수신 버퍼는 처음 할당될 때 올바르게 정렬되지만 결국 애플리케이션 버퍼에 복사해야 하는 사용자 데이터는 사용된 헤더 공간으로 인해 잘못 정렬됩니다. TCP 데이터(가장 일반적인 시나리오)의 경우 TCP, IP 및 이더넷 헤더로 인한 변화로 인해 0x36 바이트가 변경됩니다. 이 문제를 resolve 위해 드라이버는 약간 더 큰 버퍼를 할당하고 패킷 데이터를 0xA 바이트의 오프셋에 삽입하는 것이 좋습니다. 이렇게 하면 버퍼가 헤더에 대한 0x36 바이트로 이동된 후 사용자 데이터가 올바르게 정렬됩니다. 캐시 라인 경계에 대한 자세한 내용은 NdisMAllocateSharedMemory에 대한 설명 섹션을 참조하세요.

Scatter-Gather DMA 사용

NDIS 분산/수집 DMA 는 물리적 메모리의 인접하지 않은 범위에서 데이터를 전송할 수 있는 지원을 하드웨어에 제공합니다. Scatter-Gather DMA는 SCATTER_GATHER_ELEMENT 구조체의 배열과 배열의 요소 수를 포함하는 SCATTER_GATHER_LIST 구조를 사용합니다. 이 구조체는 드라이버의 send 함수에 전달된 패킷 설명자에서 검색됩니다. 배열의 각 요소는 물리적으로 연속된 Scatter-Gather 영역의 길이와 시작 물리적 주소를 제공합니다. 드라이버는 데이터 전송에 길이 및 주소 정보를 사용합니다.

DMA 작업에 Scatter-Gather 루틴을 사용하면 맵 레지스터가 사용된 경우처럼 이러한 리소스를 정적으로 잠그지 않음으로써 시스템 리소스의 사용률을 향상시킬 수 있습니다. 자세한 내용은 NDIS 분산/DMA 수집을 참조하세요.

네트워크 어댑터가 TCP 분할 오프로드(대규모 송신 오프로드)를 지원하는 경우 드라이버는 TCP/IP에서 가져올 수 있는 최대 버퍼 크기를 NdisMRegisterScatterGatherDma 함수 내의 MaximumPhysicalMapping 매개 변수로 전달해야 합니다. 이렇게 하면 드라이버에 Scatter-Gather 목록을 빌드하고 가능한 버퍼 할당 및 복사를 제거하기에 충분한 맵 레지스터가 보장됩니다. 자세한 내용은 다음 항목을 참조하세요.

수신 쪽 제한 지원

멀티미디어 애플리케이션에서 미디어 재생 중 중단을 최소화하려면 NDIS 6.20 이상 드라이버는 수신 인터럽트 처리에서 RST(수신 쪽 제한)를 지원해야 합니다. 자세한 내용은 다음을 참조하세요.

NDIS 6.20의 수신 쪽 제한미니포트 드라이버를 NDIS 6.20으로 이식하는 데 필요한 변경 내용 요약의 "코드 경로 보내기 및 받기"