Inside Windows Internals란 책에서 스레드의 퀀텀(quantum)에 대한 내용을 읽고 관련된 테스트 프로그램을 짜다가 우연히 발견한 내용입니다. 이 포스트의 내용은 제한된 환경(그러나 무시할 수 없는)에서 SQL Server 2008이 노트북 배터리의 수명을 줄일 수 있다는 것입니다. 행동에 옮기시기 전에 포스트의 내용을 잘 읽어 보시기 바랍니다.

Introduction

컴퓨터의 시간은 대개 타이머 인터럽트(timer intrrupt)라 불리는 메카니즘에 의해 갱신된다. 타이머 인터럽트는 일정 주기마다 발생하는데 컴퓨터 마다 다르다. 대부분의 x86 단일 CPU 상에서는 10 msec 내외이고 x86/x64 다중 CPU 상에서는 15.6 msec 정도이다. 타이머 인터럽트가 발생하면 Windows는 시스템 시간을 업데이트 하거나 타이머 이벤트를 발생하는 등의 업데이트 하게 된다. 더 이상 타이머 인터럽트에 대해서 알라고 하지 말자. 이걸 설명하자면 필자도 대가리(마을 이름 대가리(大佳里) 말고…)가 터질 것 같은 내용이니 걍 그런 것이 있구나 생각하는 것이 정신 건강에 좋다.

어찌 되었건 타이머 인터럽트에 의해 시간이 갱신되기 때문에 DateTime.Now와 같은 일반적인 시간 관련 함수/메서드를 통해 15.6 msec 이하의 시간을 측정하는 것은 부정확한 값이 되고 만다. 그래서 Stopwatch와 같은 클래스를 사용해야만 좀 더 정확한 시간 측정값을 얻을 수 있다.

타이머 인터럽트와 배터리가 무슨 소용이 있냐고? SQL Server는 쿼리 시간 측정, 이벤트 발생 시간 등 다양한 타이밍 관련 요소를 가지고 있다. 그런데… 어떤 쿼리가 2-3 msec 정도로 매우 빠르게 수행되면 SQL Server가 이 쿼리의 시간을 측정하는데 매우 부정확한 값, 예를 들어 0 msec으로 측정할 수도 있게 된다. SQL Server가 다음 의사 코드와 같이 작성되어 있다면 말이다.

   1: DateTime beforeQuery = DateTime.Now;        // 시작전 시간 측정
   2: ExecuteQuery(……);                            //  쿼리 수행!
   3: DateTime afterQuery = DateTime.Now;         // 쿼리 수행 후 시간 측정
   4: // 수행 시간 계산!
   5: TimeSpan elapsed = afterQuery.Subtract(beforeQuery);

재수 없이 쿼리가 수행되는 동안 타이머 인터럽트가 발생하지 않으면 시스템 시간이 갱신되지 않으므로 쿼리 수행 전/후의 시간이 같을 수도 있다는 것이다. 이 경우, 3 msec로 수행되는 쿼리가 하루에 백만 번 발생한다 할지라도 SQL Server는 자신이 부하를 많이 받지 않고 있다고 판단할 수도 있다!

물론 SQL Server 팀이 이렇게 무식하게 코드를 작성하지는 않을 것이다. SQL Server는 다른 여러 가지 방법을 사용한다. 예를 들어, CPU의 클럭(1.7GHz 니 3.0 GHz 니 하는 거 말이다)을 사용하여 시간을 측정하거나, QueryPerformanceCounter 라 불리는 아주 세밀한 타이밍 카운터를 사용한다는 말이다. 영문이지만 다음 글에 SQL Server가 사용하는 타이밍 기법을 알 수 있다.

How It Works: SQL Server Timings and Timer Output (GetTickCount, timeGetTime, QueryPerformanceCounter, RDTSC, …)

SQL Server 2005 SP3 / SQL Server 2008 타이밍 기법

문제는 SQL Server 2005 SP3와 SQL Server 2008 에서 발생한다. 위 블로그 글에서 지적하듯이 이전 버전의 SQL Server들이 사용했던 타이밍 기법들은 타이머 인터럽트에 비해 정확하지만 일부 환경에서 문제를 유발할 수 있다. 예를 들어 CPU 클럭에 기반하는 타이밍 기법은 절전 모드 상에서 CPU 클럭이 변경될 수도 있고, 일부 AMD 시스템에서 QueryPerformanceCounter가 문제를 일으키기도 했다.

그래서 SQL Server 2008은 타이머 인터럽트가 15.6 msec이 아닌 1 msec 마다 발생하도록 timeBeginPeriod 라는 멀티미디어 API를 호출하고, 1 msec의 타이머 인터럽트로 인해 정확한 타이밍과 더불어 기존 타이밍 기법의 문제들을 모두 해결할 수 있었다. 그리고 SQL Server 2008의 이런 향상은 SQL Server 2005 SP3에도 적용되었다.

짧은 타이머 인터럽트와 배터리 수명

드디어 본론으로 들어와서… 타이머 인터럽트가 짧으면 CPU와 같은 시스템 하드웨어들이 절전 모드를 활용해 배터리를 아끼고 배터리의 수명을 늘여주는 것을 방해하게 된다. 시스템 하드웨어들이 절전 모드로 들어갔다가 다시 복원하는 데에도 일정 수준의 전원이 필요한데 짧은 타이머 인터럽트로 인해 오히려 전원을 더 많이 사용하게 된다는 말이 되겠다. 다음 링크에서 필자의 말을 확인할 수 있을 것이다.

Timers, Timer Resolution, and Development of Efficient Code

테스트

정말 여러분의 노트북에서 타이머 인터럽트가 1초로 설정되어 있는지 확인하는 방법은 Sysinternals의 멋진 유틸리티인 ClockRes를 다운로드 받아 수행시켜 보면 된다. 만약 ClockRes가 다음과 같은 출력을 발생한다면 타이머 인터럽트의 주기가 1 msec 인 것이다.

ClockRes v2.0 - View the system clock resolution
Copyright (C) 2009 Mark Russinovich
SysInternals - www.sysinternals.com

Maximum timer interval: 15.600 ms
Minimum timer interval: 0.500 ms
Current timer interval: 1.000 ms             <= 요기에 주목

반대로 ClockRes가 Current timer interval의 값으로 15.6 비스므레한 값을 출력한다면 타이머 인터럽트의 주기가 기본 설정으로 사용 중인 것이 된다. SQL Server가 구동 중임에도 불구하고 15.6 mesc 주기로 타이머 인터럽트가 발생한다면 배터리의 수명이 단축되는 문제는 없을 것이다. (해당 사항 없는 버전의 SQL Server를 사용하거나 아니면 최신 패치를 죄다 받았거나 겠지……)

필자의 경우, SQL Server 2008 R2 Developer Edition을 사용하고 있는데, SQL Server 2008이 구동 중인 상황에서는 Current timer interval 의 값이 위와 같이 1.000 로 출력되었다. 그리고 SQL Server 2008 서비스를 종료하면 다시 기본 값인 15.6 으로 출력이 된다. 고로! SQL Server 2008을 구동하면 배터리의 수명을 단축시킬 수 있는 상황이 발생할 수도 있는 것이다. (항상 그렇지는 않다!)

주의 사항

주의할 사항은 AC 전원을 사용하는 경우 배터리를 사용하지 않기 때문에 문제가 없다. 여기서 말하는 상황은 타이머 인터럽트가 1 ms 으로 설정된 상황에서 AC 전원 없이 배터리를 사용하는 경우에만 초과 전력을 사용하여 배터리의 수명이 최대 25% 까지 줄어들 수 있다는 것이다. “나는 항상 AC 전원만 쓰는데?” 라고 말하는 사람은 걍 신경 끄고 그대로 사용하면 되겠다. “난 SQL Server 2005 SP2 쓰는데?” 이분도 걍 신경을 끄고 다른 글이나 보러 가면 되겠다.

해결 방법

해결 방법은 http://support.microsoft.com/kb/972767/en-us 핫 픽스를 설치하면 된다. 그런데 이 핫 픽스의 내용을 조금 읽어 보면 이 핫 픽스가 SQL Server Express 에디션과 SQL Server Report Services의 문제만을 해결한다고 되어 있다. 역시… 필자의 노트북엔 최신의 SQL Server 2008 R2 가 설치되어 있음에도 타이머 인터럽트가 1 msec로 설정되어 있드라… 된장…

2011-04-17 업데이트 내용
SQL Server 2008 R2가 설치된 64비트 Windows 7에서는 타이머 인터럽트가 기본 값인 15.6 msec 였습니다. 반드시 타이머 인터럽트 시간을 확인한 후에 조치하시기 바랍니다.


다른 해결 방법이라기 보다는 피해가는 방법은 SQL Server 2008을 구동할 때 명시할 수 있는 시작 옵션을 통해 1 msec 타이머 인터럽트를 사용하지 않도록 강제 하는 것이다. 시작 옵션으로는 –T8038 을 주어야 한다. 구체적인 설정 방법은 다음 링크를 참고 하도록 하자.

방법: 서버 시작 옵션 구성(SQL Server 구성 관리자)

-T8038 옵션을 명시한 후 SQL Server를 다시 구동하자. 그리고 다시 ClockRes 유틸리티를 돌려보면 타이머 인터럽트 주기가 15.6 msec으로 출력될 것이다.

타이머 인터럽트 주기가 늘어남에 따라서 SQL Server 2008이 출력하는 타이밍 정보가 부정확할 수도 있다. 하지만 사실 노트북에 SQL Server를 설치한 경우는 운영을 위한 것이 아니라 개발이나 테스트/데모 등의 목적이기 때문에 타이밍 정보가 초큼 부정확해도 시비걸 사람은 없을 것이다. 고로!!! 미숀 꼼쁠리도.

다시 한번 강조하는 주의 사항

꼭 이렇게 써 놓으면 미친듯이 SQL Server가 설치된 컴터들을 돌아다니면서 -T8038을 난무하는 인간들이 있다. 그래서 강조한다. 노트북이 아닌 서버에 -T8038을 적용했을 때에는 필자는 책임질 수 없다. 또! AC 전원이 사용되는 상황에서 1 msec 의 타이머 인터럽트는 문제를 유발하지 않는다. 배터리를 사용하는 상황에서만 짧은 타이머 인터럽트 주기가 배터리의 수명을 단축시킬 수 있다는 점을 명심해 두자.

마지막 뽀너스로 짧은 타이머 인터럽트는 높은 품질의 애니메이션, 고화질 동영상, 고음질 음악을 재생할 때도 사용된다(물론 재생하는 동안만). 고로 배터리 사용시 과도한 야동 시청은 육체/정신 건강에도 해롭고 노트북 배터리에도 해로운 짓이 되겠다….

간단하게 글하나 쓰려다가 또 길어져 버렸네….. 새벽 4시다… 줴길… 역시 지 버릇 개 못주는군하!!!


경고 : 이 글을 무단으로 복제/스크랩하여 타 게시판, 블로그에 게시하는 것은 허용하지 않습니다.