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 8 posts - 1 through 8 (of 8 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!

              #13999
              xiangenmin
              Participant

                With your team’s technical guidance, my C# application integrating your driver has successfully reduced CPU utilization and is running stably. However, under the current operational parameters (20Mbps uplink/30Mbps downlink), the CPU utilization rate remains between 5%-10%. Are there any additional optimization methods to further reduce the software’s CPU resource consumption?

                #14000
                xiangenmin
                Participant

                  #14001
                  Vadim Smirnov
                  Keymaster

                    Thank you for the update — I’m glad to hear that the integration is running stably and that you’ve already achieved a noticeable reduction in CPU usage.

                    Performance tuning is a nuanced and context-dependent task. To explore further optimization opportunities, I would recommend using a tool like the Visual Studio Profiler to analyze where the application is spending the most CPU time. This will provide valuable insights into any remaining bottlenecks that could be addressed.

                    That said, if the goal is to reduce CPU usage to near-zero levels, it’s worth noting that some processing overhead is inevitable — even with relatively modest network loads such as 20Mbps uplink and 30Mbps downlink. Still, profiling should give us a clear picture of what’s realistically achievable in your setup.

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