성능로그를 통한 GC에 의한 High CPU 확인

Garbage Collector(GC) .Net Framework / CLR 에서 Memory를 관리해주는 Module 이다. 그러므로, 개발자의 의도와 상관없이 적절한 시점에 GC가 수행하고, 그것도 비동기적으로 발생하며, 그에 의해 메모리를 효율적으로 사용할 수 있도록 해준다. 문제는 GC가 비동기적으로 수행됨에 의해 임의의 시점에 GC의 수행과 더불어 응용프로그램의 성능에 영향을 줄 수도 있다라는 것이다. 성능에 영향을 미친다는 것은 예상보다 긴 시간 동안에 GC가 수행되고 이에 의해 High CPU상태가 User가 견디기 힘들 정도로 지속될 수 도 있다는 것이다.

 

그렇다면, .NET Application High CPU일 경우에 GC에 의해 영향을 받은 것인지 어떻게 체크할 수 있을 까. 사실 해당 작업은 그렇게 쉽게 확인할 수 없지만, 몇 가지 요소를 통해서 문제를 좁혀나갈 수 있다.

 

첫 번째로는 %Time IN GC/.NET CLR Memory 성능 카운터의 값을 확인하는 것이다. 이 값은 최근 GC가 수행함에 의해 소요된 시간의 백분율 값이다. 설명은 그렇게 되어 있는 데, 일단, 50% 이상으로 높다라면, Managed Heap에서 Allocation 되는 패턴을 확인해야 한다. 일반적으로 평균 5% 정도나 10%이하라면 신경 쓸 필요가 없어 보인다. 그리고, 5% 이하라면 의미 있는 Data가 아니므로, 어떠한 판단을 하기가 어렵다. 하지만, 50% 이상이라면, Allocated Bytes/sec 를 확인하여 Allocation rate 를 확인하는 것이 필요하다.

 

실제로, Performance Monitoring을 통해서 % Processor Time High CPU상태로 어느 정도 지속이 된다면, 문제라고 판단한다. 그러므로, High CPU를 유발하는 Thread Check 하고, Thread Stack Check하여 Looping과 같은 Code에 의해 Thread High CPU를 유발하는 것이 아닌가 확인하는 작업이 필요하게 되는 데, 해당 Thread가 역시 GC Thread일 수도 있다. 이는 Memory Dump에서 성능로그에 High CPU를 유지하는 Thread ID Check하여 해당 Thread ID에 대한 메모리 덤프의 Thread Check했을 때, SOS extension에서 제공하는 !threads result GC라고 표시된 Thread와 일치한다면, GC에 의해서 High CPU라고 확인할 수 있을 것이다. 또는 %Time IN GC의 값이 변동이 있을 때, 예를 들어, High에서 Low로 떨어지거나 Low에서 High로 상승하는 시점에 %Processor Time Peak를 친다면, GC에 의해서 High CPU가 유발되었다고 추측할 수도 있다. 이는 메모리 덤프에 의한 Double check가 필요하다.

 

% Time IN GC가 높아서 High CPU라는 것은 결국, GC가 너무 자주 수행되거나 오랫동안 수행된다는 것이다. 그러므로, 이미 언급한 것처럼, 일반적인 Allocation rate이 높아서 GC가 자주 발생하는 것이라면, Allocation pattern에 대한 체크가 필요하며, 두 번째는 # GenX GC counters를 확인하는 것이다. 이는 얼마나 자주 GC가 수행되는 지 확인할 수 있을 것이다. 일반적으로 초점이 되는 것은 Gen2 GC이다. Gen0/Gen1 Performance에 크게 영향을 주지 않는 다. 하지만, Gen2 Large Object Heap의 경우는 Performance에 영향을 많이 준다. 일반적으로 gen2:gen1 의 비율이 1:10+ 정도라면 크게 우려할 정도가 아니다. 하지만, 그렇지 않다면, gen2에서의 GC 수행이 영향을 미쳤다고 추측하게 된다. 이 경우는 응용프로그램이 gen2에 적재되어 있을 수 있고, 계속해서 promotion gen1으으부터 이뤄지고 있다고 판단할 수 있는 데, 결국, gen2까지 살아남은 Objects에 대한 Verification이 필요하다. Gen2까지 살아 남을 필요가 있는 Objects들인가.. 이는 메모리 덤프에서 SOS !dumpheap –stat –gen2 command를 통해서 Objects를 확인할 수 있다. 그러므로, 응용프로그램의 Performance를 위해서 Objects의 조기에 release 하는 Code적인 장치가 필요할 수도 있다. 결국, 이러한 경우에는 개발자가 성능적인 이유를 위해서 적절한 Objects release 를 간여해야 한다는 것이다. GC만을 믿을 수 없다.

 

마지막으로는 모호하긴 하지만, #induced GC값이다. 해당 값은 프로세스가 시작된 이후에 GC의 발생횟수를 나타낸다. 이 값이 너무 큰 값이라면, 이는 응용프로그램의 버그를 의심할 수 있다. 가끔 메모리 힙의 크기가 증가되는 것을 줄이기 위해서 강제적으로 GC.Collect 를 호출하는 경우가 있는 데, 이로 인하여 오히려 performance 에 문제가 된 것은 아닌지 확인해 볼 수도 있을 것 같으며, 그렇지 않으면, Heap Corruption 발생하여 비 정상적인 동작이 있을 수도 있다. 이 경우도 High CPU가 될 수 있음을 확인해야 할 것이다

 

 

by 강세윤 | 2009/06/22 11:33 | Windows debugging | 트랙백 | 덧글(0)
트랙백 주소 : http://byung.egloos.com/tb/5014161
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]

:         :

:

비공개 덧글

< 이전페이지 다음페이지 >