프로그래밍/C#, .NET

[.NET] 타이머(Timer)와 스톱워치(Stopwatch)의 정밀도 차이

당근천국 2022. 6. 14. 15:30

다른 포스팅에서 타이머의 정밀도 문제로 FPS(Frames Per Second)를 구하면 정확하지 않다고 이야기를 했었습니다.

(참고 : [.NET] 게임 루프(Game Loop)를 구현할 때는 'Environment.TickCount'를 사용하면 안 된다. )

 

스톱워치(Stopwatch)를 이용한 정밀 타이머를 만들어 보고,

이것을 이용하여 둘의 차이가 얼마나 나는지 알아봅시다.

 

 

1. 타이머 구현

스톱워치 타이머를 구현하려면

1) 무한 루프를 돌리고

2) 우리가 원하는 간격에 이벤트를 보내는

3) 비동기 쓰래드를 만들어야 합니다.

 

구현은 아래와 같이 합니다.

public async Task Start()
{
   bool bLoop = true;
 
    long nLastTime = 0;
 
    Stopwatch sw = new Stopwatch();
    sw.Start();
 
    await Task.Run(() =>
    {
        while (true == bLoop)
        {
            //현제 틱
            long nTicksNow = sw.ElapsedTicks;
 
            //마지막 틱 + 프레임 만큼 시간이 지났는지 확인
            if (nTicksNow > nLastTime + this.FrameTick)
            {
                nLastTime = nTicksNow;
                //업데이트 알림
               //this.OnElapsedCall();
                bLoop = false;
            }
        }
 
       bLoop = false;
    });
}

 

 

 'StopwatchTimer' 라이브러리

이것을 타이머와 비슷한 구조로 만든 라이브러리입니다.

github - dang-gun/DotNetSamples/StopwatchTimer/

 

아래와 같이 초기화합니다.

StopwatchTimer.Timer stopwatchTimer;
 
stopwatchTimer = new StopwatchTimer.Timer();
stopwatchTimer.Interval = 10;
stopwatchTimer.OnElapsed += (sender) => { };

 

아래와 같이 사용합니다.

//타이머 시작
await this.stopwatchTimer.Start();
 
//타이머 
this.stopwatchTimer.Stop();

 

 

2. 비교하기

비교에 사용한 샘플 프로젝트는 아래에서 받을 수 있습니다.

github - dang-gun/DotNetSamples/StopwatchTimerTest/

 

간격을 0.01초(10ms)로 해서 타이머와 스톱워치를 비교해 봅시다.

10ms * 100 = 1000

1~2정도는 타이밍 때문에 차이가 있을 수 있지만 타이머는 '631'로 많이 부족한 정밀도를 보이는 군요.

 

 

간격을 0.1초(100)로 해봅시다.

윈도우의 FPS가 60이라 16보다 큰 간격이면 비교적 정확한 것을 알 수 있습니다.

 

 

마무리

테스트도 할 겸 스톱워치 타이머도 만들 겸 해서 써본 포스팅입니다.

무한루프에 의한 성능저하가 있는지까지는 모르겠네요.

 

여기서 주의해야 할 것이 운영체제별로 1초당 틱수가 차이가 납니다.

'Stopwatch.Frequency'를 통해 지금 운영체제가 1초당 몇 틱을 사용하는지 알 수 있습니다.