몇 일전 Visual Studio 2012 Update 2가 정식 릴리스 되었습니다. 다양한 새로운 기능들이 많이 추가되었습니다만 이번 포스트에서는 유닛 테스트 프로파일링에 대해 몇 마디 하고자 합니다.

About Profiling

테스트 프로파일링(Test Profiling)은 유닛 테스트 코드에 대한 프로파일링을 말한다. 이 기능은 Visual Studio 2012 Update 1에 처음 추가되었지만 사소한 버그가 있었다. Update 2에 와서는 별다른 문제없이 사용할 수 있다.

프로파일링이란 단어를 처음 들어본 독자에겐 미안하지만 이 글을 읽기 전에 프로파일링이 무엇인지 모르는 독자를 위해 위키의 정의를 살펴보면 다음과 같다.

프로파일링(profiling, 프로그램 프로파일링/소프트웨어 프로파일링) 또는 성능 분석은 프로그램의 시간 복잡도 및 공간(메모리), 특정 명령어 이용, 함수 호출의 주기와 빈도 등을 측정하는 동적 프로그램 분석의 한 형태이다. 프로파일링 정보는 대개가 프로그램 최적화를 보조하기 위해 사용된다. 프로파일링은 프로파일러(profiler)라는 도구를 사용하여 프로그램 소스 코드나 이진 실행 파일을 계측 분석함으로써 수행한다.
출처-위키백과

프로파일링이란 간단히 말해 코드의 성능이나 메모리 사용량 등의 지표를 분석하는 작업을 말하는 것이 되겠다. 물론 Visual Studio 역시 프로파일링 도구를 지원하며 여러분의 코드의 아픈 부분을 지적질하는 기능을 포함하고 있다. 한번 쯤은 자신의 코드가 얼마만큼 ‘느린지’ 얼마나 메모리를 사용하는지 궁금하다면 한번 쯤 수행해 볼만한 도구이다. 상세한 방법은 패스~~~

What’s the Test Profiling

그렇다면, 테스트 프로파일링이란 무엇인가? 다름 아닌 내 유닛 테스트 코드에 대해 프로파일링을 해준다는 것이 되겠다. 이미 프로파일링 기능이 있다면서 유닛 테스트에 대한 프로파일링이 뭐 그리 대단한 기능이냐고?

Visual Studio를 포함하여 프로파일링 도구들을 한 번이라도 사용해 본 독자라면, 프로파일링을 위해 준비하는 설정이 아주 간단하지 않다는 것을 알 것이다. Visual Studio라면 성능 탐색기(Performance Explorer)를 열고 프로파일링 하고자 하는 대상 모듈(DLL, EXE)을 선택하고 어떤 부분에 대한 측정인가에 대한 설정 등등…… 유닛 테스트를 프로파일링 하고자 한다면 유닛 테스트를 수행하는 .exe 모듈이 무엇이고 내 유닛 테스트가 포함된 어셈블리를 추가해 주어야 할 것이며 기타 설정 작업들을 완료해야 할 것이다. 하지만 이 설정 작업은 상당히 복잡한데, 유닛 테스트가 단일 exe에 의해 수행되지도 않을 뿐 더러 어떤 모듈을 프로파일링 대상으로 삼기도 애매하다. 심지어 성능 탐색기에서 프로파일링을 시작하기도 어렵다.

imageimage

이런 문제에 대해 고객들의 불평을 인지했는지 몰라도 Visual Studio 2012 Update 1에는 테스트 프로파일링 기능이 추가되었다. 이 기능은 단 한번의 클릭으로 유닛 테스트에 대한 프로파일링을 시작하고 결과를 수집하여 보여준다. 테스트 프로파일링 기능은 “테스트(Test)” 메뉴나 유닛 테스트를 우클릭 함으로써 시작할 수 있다.

테스트 프로파일링을 시작하면 Visual Studio는 보통 유닛 테스트를 수행하는 것과 동일하게 유닛 테스트를 수행하며 테스트가 완료되면 프로파일링 결과를 자동으로 표시해 준다.

image

Visual Studio 2012 Update 1에서는 프로파일링 결과를 자동으로 표시 해주지 않는 현상이 있었지만(TestResults 폴더에서 수동으로 .vsp 파일을 열어야만 함) Update 2에서는 이러한 문제가 발견되지 않았다.

Why Test Profiling?

테스트 프로파일링을 왜 언제 써야 하는 걸까? 일단 유닛 테스트를 사용하고 있지 않은 독자들은 살포시 다른 사이트에 놀러 가는 것이 좋을 듯 하다. 물론 여기까지 읽어준 것으로도 감사하게 생각하는 바이다.

필자와 같이 수백 개의 유닛테스트를 돌리 다보면 가끔 “이 숏키는 왤케 느려?” 라는 말이 튀어나오는 유닛 테스트들을 발견하곤 한다. 바로 이럴 때 테스트 프로파일링을 구동하면 되겠다. 코드의 어떤 부분(메서드)이 가장 많이 호출되고 있으며 이 코드가 전체 수행 시간 중 차지하는 비율 등이 표시되며 이 정보들을 바탕으로 비 효율적인 코드가 존재하는지 살펴보고 튜닝을 하면 된다. 필자의 경우 생각하는 것 보다 느린 유닛 테스트를 발견했고 덕분에 비효율적인 코드를 발견하고 수정할 수 있었다.

Limitiation

테스트 프로파일링은 계측(instrumentation)을 통한 프로파일링만을 제공하며 샘플링(sampling), 메모리 사용량, 리소스 경합 등에 대한 측정은 제공하지 않는다. 또한, 하나의 단일 유닛 테스트에 대해서만 프로파일링이 가능하다. 또, 원 클릭에 의해 수행되기 때문에 프로파일링에 대한 상세한 설정이 불가능 하다. 여기까지가 필자가 발견한 제약 사항이지만 아직 필자가 발견하지 못한 사항이 추가로 존재할 수도 있다.

Tip

마지막으로 테스트 프로파일링을 사용할 때 발생할 수 있는 문제와 해결 방법을 알려주겠다.

계측을 통한 프로파일링 작업 시 발생하는 문제는 강력한 이름(strong name)을 가진 어셈블리를 프로파일링 할 때 이다. 다시 말해 .snk 파일로 서명한 어셈블리를 계측할 때 발생하는 문제인데, 성능 탐색기를 사용할 때에는 다시 서명(re-sign)등을 거쳐 문제를 해결할 수 있지만 테스트 프로파일링은 설정이 전혀 없기 때문에 다음과 같은 예외가 발생할 수 있다.

형식을 가져올 수 없습니다. 오류: System.IO.FileLoadException: 파일이나 어셈블리 'UnitTestProject1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ad4c2c837cb5aa40' 또는 여기에 종속되어 있는 파일이나 어셈블리 중 하나를 로드할 수 없습니다. 강력한 이름 유효성 검사에 실패했습니다. (예외가 발생한 HRESULT: 0x8013141A)
파일 이름: 'UnitTestProject1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ad4c2c837cb5aa40' ---> System.Security.SecurityException: 강력한 이름 유효성 검사에 실패했습니다. (예외가 발생한 HRESULT: 0x8013141A)

이 때에는 sn.exe –Vr 옵션으로 잠시 동안 해당 어셈블리(들)에 대한 강력한 이름 유효성 검사를 Off 시키면 된다. Vr 옵션은 보안적으로 위험하므로 개발 장비에서만, 그것도 잠시 등록해 두고 Vx 옵션으로 바로 제거를 하는 것이 좋다.

또 다른 팁은 sn.exe –Vr 옵션을 통해 강력한 이름 유효성 검사에 대한 설정을 한 경우에도 발생하는 문제이다. 다름 아닌 sn.exe가 32비트인가 64비트인가에 따라 서로 다른 영역(32비트/64비트)에 강력한 이름 유효성 검사 제외 목록을 기록하기 때문이다. 따라서 자신이 32비트 유닛 테스트를 수행하는지 64비트 유닛 테스트를 수행하는지에 따라 32비트/64비트 sn.exe를 사용해 주면 되겠다.

테스트 프로파일링을 통해 자신의 코드가 성능적으로 얼마나 좋은지 확인해 보기 바란다.


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