본문 바로가기
프로그래밍 놀이터/iOS

[iOS Study] 디버그 도구

by 돼지왕 왕돼지 2016. 2. 26.
반응형

 [iOS Study] 디버그 도구


출처 : 아론 힐리가스의 iOS 프로그램


#endif, #ifdef, All Objects Created, allocation, allocation instrument, Allocation Lifespan, Analyze, analyze during build, arc, build configuration, build configurations, build setting, build settings, charge, code path, Configurations, CPU, cpu 디버그 측정기, Created & Destroyed, Created & Still Living, cycles & roots, debug, debug gauges, debug navigator, debug tool, default, disclosure, ExtendedDetail, Generation, generation analysis, generation 분석, heapshot, heapshot 분석, Idle, IF, Info, Instrument, instrument templet, Instruments, invert call tree, ios default, ios study, ios tutorial, Leaks, levels, live bytes, Living, mach_msg_trap, mark generation, marking, memory leak, MS, objc_msgSend, Objective-C, OS, overall, Percentage Utilized, Performance, performSelector, preprocessor macros, Private Method, Product, Profile, Project, prune, recursiveDescription, resolved, Restore, retain cycle, run, specific data mining, stack trace, static analyzer, statistics, Symbol, Target, Threads, time profiler, UIView, Utilization Comparison, Utilization over Time, Value, xcode, xcodeproj, YES, [iOS Study] 디버그 도구, 강한 참조 순환, 객체, 객체 할당, 결과물, 네트워크 입출력, 대기, 디버그, 디버그 네비게이터, 디버그 도구, 디버그 툴, 디스클로저, 디스패치, 라이브러리, 램, 리소스, 릴리즈, 링커, 메모리, 메모리 누수, 메모리 디버그 측정기, 메소드, 메소드 cpu 사용률, 모니터링, 문제, 배포, 백분율, 번들, 비공개 메소드, 빌드, 빌드 구성, 빌드 세팅, 사용량, 사용률, 성능, 세팅, 소ㅡㅅ 코드, 스키마 편집기, 스택 트레이스, 시간, 시뮬레이터, 시스템 라이브러리, 실 장비, 아론 힐리가스, 앱 스토어, 워크 스페이스, 유닛 테스트, 이슈 네비게이터, 인스턴스, 인스트루먼트, 일시정지, 장비, 전처리기 매크로, 정적 분석기, 진단 도구, 차분, 최고점, 최저점, 최적화, 추적, 측정기, 컴파일, 코드 패스, 코어, 타깃, 템플릿, 통계, 파일 입출력, 패널, 퍼센트, 프레임워크, 프로젝트, 프로파일, 플러그인, 하나의 함수, 하드웨어, 함수, 함수별 cpu 사용률, 해결, 호출을 호출자에 넘기기


-

Xcode 5 CPU와 메모리 사용량에 관한 정보를 한눈에 제공하는 디버그 측정기(debug gauges) 가 있다.



-

디버그 네비게이터는 프로그램 실행 중에(실시 정지나 중단된 경우가 아닌) CPU 와 메모리 측정기를 보여준다.



-

이 측정기들은 실제 프로그램이 실행 중인 하드웨어를 기반으로 측정한다.

Mac 은 iOS 장비보다 가용 램이 훨씬 많고 CPU 코어도 대개 더 많다.

따라서 iOS 시뮬레이터에서 프로그램을 실행하면 CPU 와 메모리 사용량은 매우 작게 나타날 것이다.



-

CPU 디버그 측정기는 편집기 패널에 CPU 리포트를 표시한다.


Percentage Utilized

     해당 장비가 가진 CPU 코어 수에 상대적인 CPU 사용량을 보여준다.

     듀얼 코어 장비는 CPU 사용률이 200% 로 보일 것이다.

     프로그램이 유휴 상태(idle) 이면 0% 여야 한다.


Utilization Comparison

     프로그램의 CPU 사용률을 다른 나머지 시스템과 비교하여 보여준다.


Utilization over Time

     프로그램의 CPU 사용률을 그래프로 나타내고 얼마나 오랫동안 실행 중인지 보여준다.

     이번 실행 중에 CPU 사용률의 최고점과 최저점도 함께 보여준다.


Threads

     Utilization over Time 그래프를 세분화하여 스레드별로 보여준다.



-

메모리 디버그 측정기도 있다.



-

어떤 플랫폼에서든 소프트웨어 개발의 일반적인 목표는 사용자에게 프로그램 성능을 최대화하기 위해 CPU 와 메모리 사용률을 가능한 한 낮게 유지하는 것이다. 프로젝트 중 조기에 측정기와 리포트를 자주 확인하는 습관을 들이는 것이 좋다.



-

인스트루먼트(Instruments)는 Xcode와 함께 포함된 프로그램으로 실행 중인 프로그램을 모니터링하고 프로그램 성능에 관한 정밀한 통계를 수집할 수 있다.

인스트루먼트는 여러 플러그인으로 구성된다.

객체 할당, 메소드/함수별로 CPU 사용률, 파일 입출력, 네트워크 입출력 등을 검사한다.



-

Allocations 인스트루먼트는 생성된 모든 객체와 그 객체가 메모리를 얼마나 차지하는가에 대해 알려준다.

좀 더 정확한 데이터를 얻기 위해서는 실제 장비를 사용해야 한다.



-

프로그램을 프로파일하기 위해서는 워크스페이스 좌상단 모서리에서 Run 버튼을 누르고 있는다.

그러면 팝업 메뉴가 나타나는데 그 메뉴에서 Profile 을 선택한다.


인스트루먼트가 시작되면 어느 인스트루먼트 템플릿을 사용할 것인지 묻는다.

8가지 이상의 항목이 있으며, 스크롤하면 더 많은 항목이 보인다.



-

Allocations 인스트루먼트에서는 객체가 몇 개 할당됐는지, 살아있는 인스턴스가 차지하는 메모리 크기는 얼마인지 등을 알 수 있고, Stack Trace 를 통해 어디서 만들어졌는지도 볼 수 있다.


#Living 열은 객체가 몇 개 할당됐는지를 보여준다.

Live Bytes 는 살아있는 인스턴스가 차지하는 메모리 크기를 보여준다.

#Overall 열은 프로그램이 작동하는 동안 메모리에서 해제된 경우를 포함해서 객체가 모두 몇 개나 생성됐는지 보여준다.







-

좌측 패널의 Allocation Lifespan 을 통해서 [ All Objects Created ], [ Created & Still Living ], [ Created & Destroyed ] 를 선택해서 볼 수 있다.

ExtendedDetail 영역에 나타나는 스택 트레이스를 통해 해당 인스턴스가 어디서 만들어졌는지 볼 수 있다.

여기서 회색 항목들은 시스템 라이브러리 호출이다.

검은색 텍스트가 우리가 만든 코드이다.

더블 클릭하면 코드와 함께 퍼센트들을 볼 수 있는데, 여기서 각 퍼센트는 해당 메소드 호출에 할당된 메모리 양이다. ( 다른 메소드와의 비교값 )



-

Generation 분석(또는 Heapshot 분석) 을 통해 특정 이벤트에 어떤 객체가 할당되는지 확인하기 좋다.

Generation Analysis 카테고리에서 Mark Generation 을 클릭하여 marking 을 하여 차분을 확인할 수 있다.


첫 클릭에 Generation A 카테고리가 생긴다.

제네레이션(generation)을 지정하기 전에 발생한 모든 할당을 보려면 이 카테고리 옆의 디스클로저 버튼을 클릭하면 된다.

Mark Generation 을 다시 누르면 Generation B 카테고리가 생긴다.

Generation B 옆의 디스클로저 버튼을 클릭하면 첫 번째 제네레이션 이후의 모든 할당을 나타낸다.


특정 이벤트에 어떤 객체가 할당되는지 확인하는 데 매우 유용하다.


처음 시작한 모든 객체 목록으로 되돌아가기 위해 사이트 경로바에서 Generations 라고 된 팝업 버튼을 선택하여 Statistics 로 변경한다.



-

Generation 분석은 메모리 사용 경향을 인식하는 데 가장 유용하다.



-

Time Profiler 인스트루먼트는 프로그램의 CPU 사용에 관한 완전한 통계를 제공한다.


인스트루먼트의 좌상단 모서리의 일시정지 버튼을 클릭하고 좌측 패널에서 Invert Call Tree 박스를 체크하면 테이블의 각 행은 하나의 함수 또는 메소드를 표시한다.

왼쪽 열은 그 함수가 소비한 시간(밀리초 단위의 시간과 총 실행 시간 중 백분율) 을 표시한다.



-

"이 함수에서 X 퍼센트의 시간을 소비했다면 프로그램에 문제가 있는 것이다." 와 같이 말할 수 있는 규칙은 없다.



-

Time Profiler 는 프로그램의 거의 모든 함수와 메소드 호출을 보여준다.

만약 프로그램 코드의 특정 부분에 초점을 맞추고 싶다면 프로파일러의 결과물을 일부 잘라낼 수 있다.


예를 들어 목록에서 종종 mach_msg_trap 함수가 매우 높은 수치를 보일 수 있다.

이 함수는 입력을 기다릴 때 메인 스레드가 위치하는 곳이다.

이 함수에서 시간을 소비하는 것은 나쁜 것이 아니다.


잘라내고 싶은 결과물을 클릭하고 Specific Data Mining 아래의 Symbol 버튼을 클릭하면, 해당 창에 함수가 추가된다.

Charge 대신 Prune 으로 바꾸면 된다.

이렇게 하면 해당 함수에 대한 profile 결과는 무시된다.

Restore 를 클릭하여 다시 전체 시간에 추가할 수 있다.


Charge 는 호출하는 메소드쪽으로 시간을 합산한다는 의미이다.



-

Time Profiler 에서 심벌 목록을 줄이는 다른 옵션으로 Objective-C 호출만 보기, 시스템 라이브러리 숨기기, 호출을 호출자에게 넘기기 등이 있다.



-

일부 자주 사용되는 함수 호출은 항상 많은 CPU 시간을 사용한다.

이 시간의 대부분은 무해하고 불가피한 것이다.

예를 들어, objc_msgSend() 함수는 모든 Objective-C 메시지의 핵심 디스패치 함수이다.



-

ARC로 메모리를 관리하는 현재는 이 인스트루먼트가 덜 유용해졌다.

하지만 여전히 강한 참조 순환으로 메모리 누수가 발생할 수 있다.

Leaks 는 강한 참조 순환을 찾는 데 도움을 줄 수 있다.


사이트 경로바에서 Leaks 팝업 버튼을 선택하고, Cycles & Roots 로 변경하면, 강한 참조 순환을 그래픽 화면으로 보여준다.



-

인스트루먼트 사용에 많은 시간을 투자하기 전에 명심해야 하는 것이 있다.

성능 문제가 없다면 인스트루먼트 결과 한 줄 한 줄에 초조해하지 말아야 한다.

현재 가지고 있는 문제를 진단하는 도구이지, 새로운 문제를 발견하는 것이 아니다.

먼저 제대로 작동하는 코드를 작성하고, 문제가 있다면 인스트루먼트의 도움을 받아 그 문제를 찾아 해결해야 한다.



-

인스트루먼트는 실행 중인 프로그램에서 문제를 추적하는 데 도움이 될 수 있다.

또한 Xcode 에 코드를 실행하지 않고 분석 요청을 할 수 있다.

정적 분석기는 코드가 실행되면 어떤 일이 발생할지에 대한 학습된 추론을 통해 잠재적 문제를 알려주는 도구이다.







-

정적 분석기가 코드를 점검할 때, 가능한 모든 코드 패스(code path)를 순회하면서 모든 함수와 메소드를 각각 검사한다.

코드 패스는 주어진 제어문에 따라 실행 가능한 경로 중 하나이다.

예를 들어, 하나의 if 문을 가진 메소드는 두 개의 코드 패스가 존재한다.

조건이 실패할 때와 조건이 성공할 때이다.



-

정적 분석기를 실행하려면 Run 버튼을 클릭한 채 Analyze 를 선택한다.

이슈 네비게이터에 분석 결과가 나타난다.


분석기는 어떻게 이러한 결론에 도달했는지 보여준다.



-

Xcode 프로젝트는 프로젝트 내에서 항목들 간의 규칙을 배열한 여러 세팅을 가지고 있다

또한 그 외 다른 파일들(소스 코드, 리소스, 프레임워크, 라이브러리) 에 대한 목록도 가지고 있다.

프로젝트는 .xcodeproj 확장자를 갖는다.



-

프로젝트는 언제나 최소한 하나의 타깃(target)을 가진다.

프로그램을 빌드하고 실행하면, 그것은 프로젝트가 아닌 타깃을 빌드하고 실행하는 것이다.

타깃은 특정 결과물(product)을 빌드하기 위해 프로젝트에서 파일들을 사용한다.

타깃이 빌드하는 결과물은 컴파일된 라이브러리나 유닛 테스트 번들이 될 수도 있지만 일반적으로 앱이다.



-

Xcode 는 새 프로젝트를 만들어 템플릿을 선택하면 자동으로 타깃을 만든다.

타깃을 보려면 프로젝트 네비게이터 목록에서 최상위 항목을 선택하면 된다.



-

모든 타깃은 컴파일러와 링커가 프로그램을 어떻게 빌드해야 할 지 기술한 빌드 세팅(build settings)를 포함한다.

또한 모든 프로젝트는 프로젝트 내의 타깃들이 기본으로 적용되는 빌드 세팅을 가진다.



-

빌드 세팅에서 설정 목록 위에 있는 Levels 옵션을 클릭한다.

OS, 프로젝트, 타깃이 각기 다른 레벨에서 설정 값을 볼 수 있다.

맨 오른쪽 열은 iOS Default 설정을 보여준다.

이 설정은 프로젝트의 기본값으로 재정의할 수 있다.

그 왼쪽 열은 프로젝트의 설정을 보여주고 그 이전 열은 현재 선택된 타깃의 설정을 보여준다.

Resolved 열은 실제 적용된 설정을 보여준다.

각 열을 클릭하여 해당 레벨의 값을 설정할 수 있다.



-

"static analyzer" 를 빌드 세팅 목록에서 검색한다.

Analyze During 'Build' 설정을 Yes 로 설정하여 Xcode 가 프로그램을 빌드할 때마다 항상 자동으로 정적 분석기를 실행하게 할 수 있다.

이는 빌드 시간을 급격히 늘리긴 하지만 대체로 얻는 것이 더 많다.



-

각각의 타깃과 프로젝트는 복수의 빌드 구성(build configurations)을 가진다.

빌드 구성은 빌드 세팅의 집합이다.

프로젝트를 만들면 디버그와 릴리즈라는 두 개의 빌드 구성이 생긴다.

디버그 구성의 빌드 세팅은 프로그램을 좀 더 쉽게 디버그할 수 있도록 해준다.

반면 릴리즈 세팅은 실행 속도를 높이기 위해 최적화해준다.



-

Configurations 섹션은 프로젝트와 타깃에서 사용 가능한 빌드 구성을 보여준다.

Info 탭의 Build Configuration 옵션의 스키마 편집기에서 스키마가 사용할 빌드 구성을 지정할 수 있다.



-

전처리기 매크로(Preprocessor Macros)는 코드의 조건에 따라 컴파일하게끔 한다.

이 매크로들은 빌드를 시작할 때 정의될 수도 있고 정의되지 않을 수도 있다.

전처리기 지시자로 코드 블록을 감싸고 있다면 해당 매크로가 정의되어 있어야만 컴파일될 것이다.


Build Setting 탭의 Preprocessor Macros 에서 구성의 Value 열을 더블 클릭한다.

여기에 매크로 값을 추가하면 된다.



-

UIView 는 프로그램의 전체 뷰 계층구조를 출력하는 비공개 메소드(private method) recursiveDescription 을 가진다.

하지만 앱 스토어에 배포하는 앱에서는 이 메소드를 호출할 수 없다.

따라서  Preprocessor Macros 의 DEBUG 구성에 VIEW_DEBUG 가 정의된 경우에는, DEBUG 빌드를 할 때에만 이 메소드 호출을 할 수 있도록 다음과 같이 코드 작성이 가능하다.


#ifdef VIEW_DEBUG

     NSLog(@“%@“, [self.window performSelector:@selector(recursiveDescription)]);

#endif


recursiveDescription 은 비공개 메소드이기 때문에 performSelector 방식으로 실행해야 한다.


recursiveDescription 은 뷰의 설명을 출력하고, 그 뷰의 모든 하위뷰의 설명을 출력한다.








반응형

댓글