Simulate steady CPU load and spikes
Asked Answered
T

6

43

How could I generate steady CPU load in C#, lower than 100% for a certain time? I would also like to be able to change the load amount after a certain period of time. How do you recommend to generate usage spikes for a very short time?

Tambratamburlaine answered 25/3, 2010 at 10:7 Comment(0)
S
60

First off, you have to understand that CPU usage is always an average over a certain time. At any given time, the CPU is either working or it is not. The CPU is never 40% working.

We can, however, simulate a 40% load over say a second by having the CPU work for 0.4 seconds and sleep 0.6 seconds. That gives an average utilization of 40% over that second.

Cutting it down to smaller than one second, say 100 millisecond chunks should give even more stable utilization.

The following method will take an argument that is desired utilization and then utilize a single CPU/core to that degree:

public static void ConsumeCPU(int percentage)
{
    if (percentage < 0 || percentage > 100)
        throw new ArgumentException("percentage");
    Stopwatch watch = new Stopwatch();
    watch.Start();            
    while (true)
    {
        // Make the loop go on for "percentage" milliseconds then sleep the 
        // remaining percentage milliseconds. So 40% utilization means work 40ms and sleep 60ms
        if (watch.ElapsedMilliseconds > percentage)
        {
            Thread.Sleep(100 - percentage);
            watch.Reset();
            watch.Start();
        }
    }
}

I'm using a stopwatch here because it is more accurate than the the TickCount property, but you could likewise use that and use subtraction to check if you've run long enough.

Two things to keep in mind:

  • on multi core systems, you will have to spawn one thread for each core. Otherwise, you'll see only one CPU/core being exercised giving roughly "percentage/number-of-cores" utilization.
  • Thread.Sleep is not very accurate. It will never guarantee times exactly to the millisecond so you will see some variations in your results

To answer your second question, about changing the utilization after a certain time, I suggest you run this method on one or more threads (depending on number of cores) and then when you want to change utilization you just stop those threads and spawn new ones with the new percentage values. That way, you don't have to implement thread communication to change percentage of a running thread.

Satanism answered 25/3, 2010 at 10:29 Comment(0)
F
19

Just in add of the Isak response, I let here a simple implementation for multicore:

 public static void CPUKill(object cpuUsage)
    {
        Parallel.For(0, 1, new Action<int>((int i) =>
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();
            while (true)
            {
                if (watch.ElapsedMilliseconds > (int)cpuUsage)
                {
                    Thread.Sleep(100 - (int)cpuUsage);
                    watch.Reset();
                    watch.Start();
                }
            }
        }));

    }

    static void Main(string[] args)
    {
        int cpuUsage = 50;
        int time = 10000;
        List<Thread> threads = new List<Thread>();
        for (int i = 0; i < Environment.ProcessorCount; i++)
        {
            Thread t = new Thread(new ParameterizedThreadStart(CPUKill));
            t.Start(cpuUsage);
            threads.Add(t);
        }
        Thread.Sleep(time);
        foreach (var t in threads)
        {
            t.Abort();
        }
   }
Forlini answered 23/1, 2012 at 20:32 Comment(1)
i used your function and it almost worked. 7 out of 8 cores were on the desired level, then i changed "for (int i = 0; i < Environment.ProcessorCount; i++)" to "for (int i = 0; i < Environment.ProcessorCount + 1; i++)" and now it works...Suspension
Z
5

For a uniform stressing: Isak Savo's answer with a slight tweak. The problem is interesting. In reality there are workloads that far exceed it in terms of wattage used, thermal output, lane saturation, etc. and perhaps the use of a loop as the workload is poor and almost unrealistic.

int percentage = 80;
for (int i = 0; i < Environment.ProcessorCount; i++)
{
    (new Thread(() =>
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();
        while (true)
        {
            // Make the loop go on for "percentage" milliseconds then sleep the 
            // remaining percentage milliseconds. So 40% utilization means work 40ms and sleep 60ms
            if (watch.ElapsedMilliseconds > percentage)
            {
                Thread.Sleep(100 - percentage);
                watch.Reset();
                watch.Start();
            }
        }
    })).Start();
}
Zita answered 2/3, 2017 at 15:15 Comment(0)
B
1

Each time you have to set cpuUsageIncreaseby variable. for example:

1- Cpu % increase by > cpuUsageIncreaseby % for one minute. 2- Go down to 0% for 20 seconds. 3- Goto step 1.

     private void test()
        {
            int cpuUsageIncreaseby = 10;
            while (true)
            {
                for (int i = 0; i < 4; i++)
                {
                    //Console.WriteLine("am running ");
                    //DateTime start = DateTime.Now;
                    int cpuUsage = cpuUsageIncreaseby;
                    int time = 60000; // duration for cpu must increase for process...
                    List<Thread> threads = new List<Thread>();
                    for (int j = 0; j < Environment.ProcessorCount; j++)
                    {
                        Thread t = new Thread(new ParameterizedThreadStart(CPUKill));
                        t.Start(cpuUsage);
                        threads.Add(t);
                    }
                    Thread.Sleep(time);
                    foreach (var t in threads)
                    {
                        t.Abort();
                    }

                    //DateTime end = DateTime.Now;
                    //TimeSpan span = end.Subtract(start);
                    //Console.WriteLine("Time Difference (seconds): " + span.Seconds);

                    //Console.WriteLine("10 sec wait... for another.");
                    cpuUsageIncreaseby = cpuUsageIncreaseby + 10;
                    System.Threading.Thread.Sleep(20000);
                }
            }
        }
Beaconsfield answered 25/3, 2010 at 10:7 Comment(0)
K
0

Share code I used for myself. After trying different options I end up with what I have below. Important note is that I used this code in Asp.Net core app and it doesn't allows .Abort() method;

        [HttpGet("load-cpu")]
        public IActionResult LoadCpu([FromQuery] int percent, [FromQuery] int seconds)
        {
            int iterations = Environment.ProcessorCount;
            ThreadLaunchOptions input = new ThreadLaunchOptions(percent, seconds);
            for (int i = 0; i < iterations; i++)
            {
                    var thread = new Thread(() => GenerateCPULoad(input));
                    thread.Start();
            }

            Thread.Sleep(TimeSpan.FromSeconds(seconds));
            return Ok();
        }

        private void GenerateCPULoad(object loadInput)
        {            
            ThreadLaunchOptions input = loadInput as ThreadLaunchOptions;
            var endTime = DateTime.Now.AddSeconds(input.Seconds); // Adjust duration as needed
            int timeThreshold = input.Percents * 10;
            Stopwatch sw = Stopwatch.StartNew();
            while (DateTime.Now < endTime)
            {
                //1000 60*10
                while(sw.ElapsedMilliseconds < timeThreshold)
                {
                    _ = Math.Sqrt(10 * this.GetHashCode()) ;
                }

                int timeLeft = 1000 - timeThreshold;
                if (timeLeft > 0)
                {
                    Thread.Sleep(timeLeft);
                    sw.Reset();
                    sw.Start();
                }
            }
            sw.Stop();
        }
        



        private record ThreadLaunchOptions(int Percents, int Seconds);

When you have code above, you can call endpoint and create beautiful plain CPU load for a specific time. For example:

http://localhost:5000/load-cpu?percent=40&seconds=20

enter image description here

Kaceykachina answered 19/2 at 19:56 Comment(0)
L
0

By using 9 out 12 available cores I am able to sustain roughly 75% CPU utilization:

Parallel.ForEach(Enumerable.Range(0, 9), i =>
{
    while (true)
    {
    }
});

enter image description here

Longsufferance answered 9/3 at 14:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.