프로그래밍/C#

[C#] Sleep을 이용하여 CPU부하줄이기, Sleep(0)의미

ss-pro 2023. 7. 18. 23:12
반응형

While문이라 For문에서 무한루프를 돌리거나 오래도록 반복해서 작업을 해야되는 경우가 있습니다. 이때 CPU부하가 올라가는데 Sleep을 적절이 이용해서 CPU부하를 줄일 수 있습니다. Sleep을 하게되면 다른 스레드로 컨텍스트 스위칭을 하여 다른 스레드가 작업을 하게 합니다. 이렇게 해서 CPU부하도 줄이고 다른 스레드에서 작업을 할 수 있게 합니다. Sleep(0)과 0보다 큰 경우는 약간 다르게 동작하는데 관련 부분에 대해 알려드리겠습니다. 

1. Sleep(0) 
MSDN자료를 확인해보면 인수값이 0인 경우 우선순위가 동일한 스레드에서 컨텍스트 스위칭하는 부분을 알 수 있습니다. 

2. Sleep(0보다큰 경우) 
대부분 Sleep을 쓸 경우 해당시간만큰 대기를 하고 싶을 경우에 사용하는 경우가 많습니다. 이때는 우선순위에 상관없이 다른 스레드에 실행정보를 넘겨주게 됩니다.  딜레이 시간을 두어 CPU부하를 줄일 수 있습니다. 

3. Sleep값에따른 CPU점유률 비교

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
using System.Threading;
using System.Diagnostics;
 
namespace SleepTester
{
    class Program
    {
        static void Main()
        {
            // 프로세서 개수 가져오기
            int processorCount = Environment.ProcessorCount;
 
            // PerformanceCounter 객체 생성
            PerformanceCounter[] cpuCounters = new PerformanceCounter[processorCount];
            for (int i = 0; i < processorCount; i++)
            {
                cpuCounters[i] = new PerformanceCounter("Processor""% Processor Time", i.ToString());
            }
 
            int loopCnt = 1000;
            float totAverage = 0.0f;
 
            Console.WriteLine($"======================================================================================");
            Console.WriteLine($"Start Sleep(X)");
 
            for (int i = 0; i < loopCnt; i++)
            {
                if (i % 100 == 0)
                {
                    float averageCpuUsage = GetCpuUseage(processorCount, cpuCounters);
                    Console.WriteLine("Average CPU Usage: {0}%", averageCpuUsage);
                    totAverage += averageCpuUsage;
                }
            }
            Console.WriteLine($"totAverage:{totAverage / 10}");
            Console.WriteLine($"======================================================================================");
            Console.WriteLine();
 
            totAverage = 0.0f;
            Console.WriteLine($"Start Sleep(0)");
            for (int i = 0; i < loopCnt; i++)
            {
                System.Threading.Thread.Sleep(0);
                if (i % 100 == 0)
                {
                    float averageCpuUsage = GetCpuUseage(processorCount, cpuCounters);
                    Console.WriteLine("Average CPU Usage: {0}%", averageCpuUsage);
                    totAverage += averageCpuUsage;
                }
            }
            Console.WriteLine($"totAverage:{totAverage / 10}");
            Console.WriteLine($"======================================================================================");
            Console.WriteLine();
 
            totAverage = 0.0f;
            Console.WriteLine($"Start Sleep(1)");
            for (int i = 0; i < loopCnt; i++)
            {
                System.Threading.Thread.Sleep(1);
                if (i % 100 == 0)
                {
                    float averageCpuUsage = GetCpuUseage(processorCount, cpuCounters);
                    Console.WriteLine("Average CPU Usage: {0}%", averageCpuUsage);
                    totAverage += averageCpuUsage;
                }
            }
            Console.WriteLine($"totAverage:{totAverage / 10}");
            Console.WriteLine($"======================================================================================");
            Console.ReadLine();
        }
 
        private static float GetCpuUseage(int processorCount, PerformanceCounter[] cpuCounters)
        {
            // 각 프로세서의 CPU 사용량 측정
            float[] cpuUsages = new float[processorCount];
            for (int j = 0; j < processorCount; j++)
            {
                cpuUsages[j] = cpuCounters[j].NextValue();
            }
 
            // CPU 평균 사용량 계산
            float averageCpuUsage = 0;
            float sum = 0;
            foreach (float value in cpuUsages)
            {
                sum += value;
            }
            averageCpuUsage = sum / cpuUsages.Length;
            return averageCpuUsage;
        }        
    }
}
 
cs

실행결과 
 Sleep을 하지 않았을 경우와 Sleep(0) Sleep(1)을 비교해봤습니다.  Sleep하지 않았을 경우와 Sleep(0)은 프로세스가 많고 하다보니 큰차이가 없어 보이고, Sleep(0)인 경우 컨텍스트 스위칭이 이루어져 실제로는 별 차이가 없어 보이지만 다른 스레드가 처리 할 수 있도록 해주기 때문에 다른 동작을 수행 할 수 있게 합니다.  Sleep(1)의경우는 해당시간 만큼 대기를 하기때문에 현저히 Cpu부하가 감소되는 부분을 확인 할 수 있습니다. 

참고
https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.thread.sleep?view=net-7.0