In the case of c# (NdisApiDemo), the CPU usage is high when the program is compi

Home Forums Discussions Support In the case of c# (NdisApiDemo), the CPU usage is high when the program is compi

Viewing 5 posts - 1 through 5 (of 5 total)
  • Author
    Posts
  • #13972
    xiangenmin
    Participant

      In the case of c# (NdisApiDemo), the CPU usage is high when the program is compiled and run

      #13973
      xiangenmin
      Participant

        private static unsafe void PassThruUnsortedThread
        (
        NdisApi filter,
        WaitHandle[] waitHandles,
        IReadOnlyList<AutoResetEvent> waitHandlesManualResetEvents)
        {
        const int bufferSize = 32;

        var buffers = new IntPtr[bufferSize];
        for (int i = 0; i < buffers.Length; i++)
        {
        buffers[i] = (IntPtr)filter.CreateIntermediateBuffer();
        }

        while (true)
        {
        WaitHandle.WaitAny(waitHandles);
        uint packetsSuccess = 0;

        while (filter.ReadPacketsUnsorted(buffers, bufferSize, ref packetsSuccess))
        {
        for (int i = 0; i < packetsSuccess; i++)
        {
        EthernetPacket ethPacket = buffers[i].GetEthernetPacket(filter);
        if (ethPacket.PayloadPacket is IPv4Packet iPv4Packet)
        {
        if (iPv4Packet.PayloadPacket is TcpPacket tcpPacket)
        {
        //Console.WriteLine($”{iPv4Packet.SourceAddress}:{tcpPacket.SourcePort} -> {iPv4Packet.DestinationAddress}:{tcpPacket.DestinationPort}.”);
        }
        }
        }

        if (packetsSuccess > 0)
        {
        filter.SendPacketsUnsorted(buffers, packetsSuccess, out uint numPacketsSuccess);
        }
        }
        }
        }
        }

         

        The demo has high CPU usage

        c# 调用驱动的时候,16核心cpu 占用16%

        #13974
        Vadim Smirnov
        Keymaster

          The high CPU usage is likely due to the fact that the packet event is never reset. This causes the thread to continuously poll the driver without pausing.

          Solution:
          You need to reset the AutoResetEvent or ManualResetEvent in waitHandlesManualResetEvents after processing packets. This ensures the thread properly waits for new packets instead of running in a tight loop.

          Fixed Code:

          
          private static unsafe void PassThruUnsortedThread
          (
              NdisApi filter,
              WaitHandle[] waitHandles,
              IReadOnlyList<AutoResetEvent> waitHandlesManualResetEvents)
          {
              const int bufferSize = 32;
              var buffers = new IntPtr[bufferSize];
          
              for (int i = 0; i < buffers.Length; i++)
              {
                  buffers[i] = (IntPtr)filter.CreateIntermediateBuffer();
              }
          
              while (true)
              {
                  int eventIndex = WaitHandle.WaitAny(waitHandles);  // Wait for an event to be signaled
          
                  uint packetsSuccess = 0;
          
                  while (filter.ReadPacketsUnsorted(buffers, bufferSize, ref packetsSuccess))
                  {
                      for (int i = 0; i < packetsSuccess; i++)
                      {
                          EthernetPacket ethPacket = buffers[i].GetEthernetPacket(filter);
                          if (ethPacket.PayloadPacket is IPv4Packet iPv4Packet)
                          {
                              if (iPv4Packet.PayloadPacket is TcpPacket tcpPacket)
                              {
                                  // Console.WriteLine($”{iPv4Packet.SourceAddress}:{tcpPacket.SourcePort} -> {iPv4Packet.DestinationAddress}:{tcpPacket.DestinationPort}.”);
                              }
                          }
                      }
          
                      if (packetsSuccess > 0)
                      {
                          filter.SendPacketsUnsorted(buffers, packetsSuccess, out uint numPacketsSuccess);
                      }
                  }
          
                  // Reset the event to allow proper waiting
                  if (eventIndex >= 0 && eventIndex < waitHandlesManualResetEvents.Count)
                  {
                      waitHandlesManualResetEvents[eventIndex].Reset();
                  }
              }
          }
          

          Explanation:

          • Wait for an event: WaitHandle.WaitAny(waitHandles); ensures the thread only runs when a packet event is signaled.
          • Process packets normally: The loop reads packets, processes them, and sends them back.
          • Reset the event: After processing packets, waitHandlesManualResetEvents[eventIndex].Reset(); is called to prevent continuous polling.

          This should significantly reduce CPU usage.

          #13975
          xiangenmin
          Participant

            Thank you

            if (eventIndex >= 0 && eventIndex < waitHandlesManualResetEvents.Count) { waitHandlesManualResetEvents[eventIndex].Reset(); }

             

            waitHandlesManualResetEvents[eventIndex]

             

            Array index out of bounds

            此处代码会出现数组索引越界

            #13976
            Vadim Smirnov
            Keymaster

              Thank you for pointing that out. I made an incorrect assumption about the parameters, but I believe you understood the main idea correctly—when there are no packets to read, the packet events should be reset, and the thread should wait on them. I appreciate the clarification!

            Viewing 5 posts - 1 through 5 (of 5 total)
            • You must be logged in to reply to this topic.