Search code examples
c#network-programminginterfacesystemcpu

How to reduce CPU usage in network bandwidth script


I'm writing this class to monitor the bandwidth passing through all of the network interfaces. Although this whole thing works wonderfully, I want to try and reduce the CPU usage during the query. The reason is because I run this every couple of seconds and it adds about 7-8% more CPU usage to the process every time. Is there any way I can reduce the amount of CPU cycles?

PerformanceCounterCategory category = new PerformanceCounterCategory("Network Interface");
        String[] instancename = category.GetInstanceNames();

        foreach (string name in instancename)
        {
            String networkCard = name;

            const int numberOfIterations = 10;

            PerformanceCounter bandwidthCounter = new PerformanceCounter("Network Interface", "Current Bandwidth", networkCard);

            float bandwidth = bandwidthCounter.NextValue();

            PerformanceCounter dataSentCounter = new PerformanceCounter("Network Interface", "Bytes Sent/sec", networkCard);

            PerformanceCounter dataReceivedCounter = new PerformanceCounter("Network Interface", "Bytes Received/sec", networkCard);

            float sendSum = 0;
            float receiveSum = 0;

            for (int index = 0; index < numberOfIterations; index++)
            {
                sendSum += dataSentCounter.NextValue();
                receiveSum += dataReceivedCounter.NextValue();
            }
            float dataSent = sendSum;
            float dataReceived = receiveSum;


            double dout = (((8 * (dataSent)) / (bandwidth * numberOfIterations) * 100) * 1024) / 100;
            double din = (((8 * (dataReceived)) / (bandwidth * numberOfIterations) * 100) * 1024) / 100;

            dout = Math.Round(dout, 2);
            din = Math.Round(din, 2);

            string doutround = Convert.ToString(dout);
            string dinround = Convert.ToString(din);



            String output = dinround + "/" + doutround;


                GlobalsWMI.NetIOs.Add(output);



        }
        String tooutput = String.Join("AND", GlobalsWMI.NetIOs);
        GlobalsWMI.NetIOs.Clear();
        return tooutput;

Solution

  • Ok I have tried various things and I think this version is much faster:

    private string GetNetworkUsage(System.Net.NetworkInformation.NetworkInterface[] nis)
    {
    
    foreach (NetworkInterface ni in nis)
                {
                    float bandwidth = ni.Speed;
                    const int numberOfIterations = 10;
    
                    float sendSum = 0;
                    float receiveSum = 0;
    
                    float lastRec = ni.GetIPv4Statistics().BytesReceived;
                    float lastSent = ni.GetIPv4Statistics().BytesSent;
    
                    for (int index = 0; index < numberOfIterations; index++)
                    {
                        System.Threading.Thread.Sleep(10);
                        float br = ni.GetIPv4Statistics().BytesReceived;
                        float bs = ni.GetIPv4Statistics().BytesSent;
                        receiveSum += br - lastRec;
                        sendSum += bs - lastSent;
    
                        lastRec = br;
                        lastSent = bs;
    
                    }
    
                    float dataSent = sendSum;
                    float dataReceived = receiveSum;
    
                    double dout = (((8 * (dataSent)) / (bandwidth) * 100) * 1024) / 100;
                    double din = (((8 * (dataReceived)) / (bandwidth) * 100) * 1024) / 100;
    
                    dout = Math.Round(dout, 2);
                    din = Math.Round(din, 2);
    
                    string doutround = Convert.ToString(dout);
                    string dinround = Convert.ToString(din);
    
                    String output = dinround + "/" + doutround;
    
    
                    GlobalsWMI.NetIOs.Add(output);
                }
    
                String tooutput = String.Join("AND", GlobalsWMI.NetIOs);
                GlobalsWMI.NetIOs.Clear();
                return tooutput;
    }
    

    call it like this:

        System.Net.NetworkInformation.NetworkInterface[] nis = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
    
        // this is you for loop add you sleep or however you do it here
        for (int i = 0; i < int.MaxValue; i++)
        {
            Console.WriteLine(test(nis));
        }
    

    Tried this on my system and it uses less CPU and is faster but I would double check that the figures are as you expect.