如何在 C# 中生成稳定的 CPU 负载,在一段时间内低于 100%?我还希望能够在一段时间后更改负载量。您建议如何在很短的时间内产生使用高峰?
首先,您必须了解 CPU 使用率始终是特定时间内的平均值。在任何给定时间,CPU 要么工作,要么不工作。 CPU 永远不会工作到 40%。
但是,我们可以通过让 CPU 工作 0.4 秒并休眠 0.6 秒来模拟一秒钟内 40% 的负载。这使得该秒的平均利用率为 40%。
将其减少到小于一秒,例如 100 毫秒的块应该会提供更稳定的利用率。
以下方法将采用所需利用率的参数,然后将单个 CPU/核心利用到该程度:
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();
}
}
}
我在这里使用stopwatch,因为它比TickCount属性更准确,但您同样可以使用它并使用减法来检查您是否跑了足够长的时间。
要记住两件事:
要回答您的第二个问题,关于在一段时间后更改利用率,我建议您在一个或多个线程上运行此方法(取决于核心数量),然后当您想要更改利用率时,只需停止这些线程并生成新的线程即可具有新百分比值的。这样,您就不必实现线程通信来更改正在运行的线程的
percentage
。
除了 Isak 响应之外,我在这里提供了一个简单的多核实现:
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();
}
}
为了统一强调:Isak Savo 的答案略有调整。这个问题很有趣。实际上,有些工作负载在使用的瓦数、热输出、通道饱和度等方面远远超过它,并且可能使用循环,因为工作负载很差并且几乎不切实际。
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();
}
每次都必须设置 cpuUsageIncreaseby 变量。 例如:
1- Cpu % 增加 > cpuUsageIncreaseby % 一分钟。 2- 降低至 0%,持续 20 秒。 3- 转到步骤 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);
}
}
}
分享我自己使用的代码。在尝试了不同的选项之后,我最终得到了下面的结果。重要提示是,我在 Asp.Net core 应用程序中使用了这段代码,它不允许使用 .Abort() 方法;
[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);
当您有上面的代码时,您可以调用端点并在特定时间创建漂亮的普通 CPU 负载。例如:
http://localhost:5000/load-cpu?percent=40&秒=20