본문 바로가기
정보공유

NDC2018 안드로이드+유니티 네이티브 프로파일링 삽질기

by 날고싶은커피향 2018. 11. 21.
반응형

NDC2018 안드로이드+유니티 네이티브 프로파일링 삽질기




 NDC2018 안드로이드+유니티 네이티브 프로파일링 삽질기
1. 안드로이드에서 유니티 프로젝트 네이티브 프로파일링 삽질기 넥슨 라이브 인프라실 하재승
2. 하재승 라이브 서비스에 도움이 될 기술 서비스 개발 ZERO, JYP, … 게임 최적화, 게임 개발 DNF, 빅샷, 메틴2, … 오픈소스 Crow, …
3. 프로파일링
4. 프로파일링 + 최적화 관련 발표 NDC 2008 최적화와 프로파일링 – 송창규님 https://www.slideshare.net/innover/ndc08-20109236 NDC 2013 사례를 통해 살펴보는 프로파일링과 최적화 - 김이선님 http://ndcreplay.nexon.com/NDC2013/sessions/NDC2013_0008.html KGC 2014 프로파일러를 이용한 게임 클라이언트 최적화 - 김종원님 https://www.slideshare.net/freefish/kgc-2014-jongwon-kimfinal 아이펀팩토리 2018 데브데이 리눅스 게임 서버 성능 분석 - 김진욱님 https://www.slideshare.net/iFunFactory/2018-ifunfactory-dev-day03
5. NDC 2013 사례를 통해 살펴보는 프로파일링과 최적화 - 김이선님 발표 중
6. 프로파일링 방식 코드 삽입 관심가는 함수 등에 정보 수집하는 코드를 삽입하여 정보를 측정 적은 실행으로도 자세한 정보 수집가능 측정 대상에 영향을 줌 샘플링 일정 시간마다 어떤 코드가 실행 중인지 콜스택을 수집 통계적으로 의미를 가짐 - 오래 실행할 수록 정확해짐 측정하고자 하는 프로그램에 영향 최소화
7. 안드로이드 + 유니티/il2cpp 프로파일링
8. 제약 사항 비공개 모바일 프로젝트에 투입 – 최적화 지원 성능 좋은 최신 폰에서는 성능 문제가 발생하지 않음 특정 하드웨어나 OS 버전의 문제인지 확인하기 어려움 문제가 발생하는 폰에서 어떻게든 측정과 재현을 해야 했다. 안드로이드 5.0.2 (Lolipop), 2015년 출시 Qualcomm MSM8916 Snapdragon 410 제작사에 의해 심하게 커스텀된 롬
9. 기존 안드로이드 프로파일링 툴들 검토 Android Studio Android NDK Profiler 유니티 프로파일링 NVIDIA Tegra Profiler Snapdragon Profiler
10. Android Studio에 포함된 프로파일러
11. Android Studio에 포함된 프로파일러
12. Android NDK Profiler Linux gprof 의 안드로이드 포트 사용하려면 빌드할 때 같이 링크해야함 2015년 이후 더이상 지원되지 않음 해당 레파지터리에 필요하면 fplutil을 사용하라고 안내함 https://github.com/richq/android-ndk-profiler
13. fplutil 을 따라가봤더니.. ## Set of tested devices that are known to support perf. SUPPORTED_DEVICES = set([ 'mantaray', # Nexus 10 'nakasi', # Nexus 7 (2012) ]) ## Set of tested devices that are known to have broken support for per BROKEN_DEVICES = set([ 'razor', # Nexus 7 (2013) 'hammerhead', # Nexus 5 ]) https://github.com/google/fplutil/blob/master/bin/android_ndk_perf.py#L58
14. 유니티 내장 프로파일러 대체로 많이들 사용 빠르게 상황을 파악하는데 도움을 줌 설정만 잘하면 실제 폰에서 프로파일링도 가능 콜스택을 보려면 Deep Profile 옵션을 켜거나 손으로 관심있는 영역에 직접 코드를 추가해야함 모든 함수의 앞뒤에 정보를 추가하는 코드 삽입형 프로파일러
15. 유니티 내장 프로파일러(Deep Profile)의 한계 1. 프레임이 눈에 띄게 떨어짐 2. 사용이 불가능한 경우도 있음 (메모리 사용량) 3. 자주 호출되거나 콜스택이 깊을 때 프로파일 결과가 왜곡됨 프로젝트 내에 memoization 등을 활용해서 속도가 엄청 빠르지만 한 프레임에 약 2000번 호출되는 함수가 존재. 유니티 내장 프로파일러 사용시 해당 함수에 마치 심각한 성능 문제가 있는 것으로 보이게 됨 나중에 샘플링 프로파일러를 통해 해당 함수가 성능에 영향이 거의 없는 것으로 확인됨
16. Snapdragon profiler
17. Snapdragon profiler
18. NVIDIA Tegra profiler
19. NVIDIA Tegra profiler
20. NVIDIA Tegra Profiler & Snapdragon Profiler 칩 제조사들이 제공하는 Profiler NVIDIA Tegra 칩을 사용하는 폰은 매우 적다. 대부분 Snapdragon을 사용하지만.. * Requires a Snapdragon 820 (or later) processor ** Requires Android N (or an Android 6.0 device with a graphics driver that supports Vulkan) *** Requires a Snapdragon 805 (or later) processor and Android 6.0 (or later) 우리 타겟폰은 Snapdragon 410 … 커스텀된 롬으로 인해 깔리지도 않음.
21. 이런저런 조사 끝에 simpleperf
22. simpleperf CUI 프로파일링 툴 Android NDK r13b 이상에서 포함 r16b 기준으로 여러 헬퍼 python 스크립트와 함께 제공 https://developer.android.com/ndk/guides/simpleperf.html
23. 선택하지 않았던 이유 당시 사용하던 유니티 5는 NDK 버전은 r10e NDK 새로 받아야 해서.. 같이 제공된 app_profiler.py이 문서대로 동작안함 해당 폰이 arm, arm64, x86 인지 체크 하는 루틴에서 에러남 알고 있으므로 하드 코딩해서 재시도 여전히 에러남 커스텀 롬 문제일 것으로 생각했었음
24. "어떻게든" 되게 하기 스크립트 내용을 살펴보고 하려고하는 일을 손으로 직접 하기 (adb 사용) 0. simpleperf binary 복사 adb push bin/android/simpleperf /data/local/tmp 1. 앱 실행 2. simpleperf 실행 adb shell /data/local/tmp/simpleperf record --app com.xx.yy -- duration 30 -g -o /data/local/tmp/perf.data 3. 수집된 데이터 복사 adb pull /data/local/tmp/perf.data * 일반적인 폰이면 app_profiler.py 로도 충분히 할수있음
25. 실제 성능 측정 간단한 유사 마인크래프트 작성 이동에 따라 주변에 지형을 계속 생성
26. 결과 확인 perf.data 복사 후 같이 제공되는 report.py 실행 report.py --symfs binary_cache --full-callgraph -g 프로파일링 결과가 "예쁘게" 텍스트로 나옵니다 report.py --gui --symfs binary_cache --full-callgraph -g GUI.. 이긴 한데..
27. FlameGraph 좋은 결과는 좋은 Visualiztion 으로 부터! simpleperf는 flamegraph 를 위한 데이터를 만드는 기능이 없다. 그러나 perf와 파일 형식이 동일 리눅스 계열 OS로 perf.data 복사 후 (윈도우 x 맥 x) perf script perf.data --sympath binary_cache > out.perf 이후 flamegraph 사이트 에서 안내하는 대로 실행 http://www.brendangregg.com/flamegraphs.html
28. FlameGraph
29. 한계 256개 까지만 쌓고 더 수집못하는 경우가 있음 원인 파악을 못함 안드로이드 OS 문제 될때까지 반복 실행 → 자동 재실행 툴 개발 제조사 커스텀 롬 지원 문제 분석이 어려운 출력 형태 FlameGraph 활용으로 문제 해결
30. 비공개 프로젝트 최적화 성과
31. 큰 개선점 – Object Pool 당연히 이미 Object Pool 사용 프로파일링 - 여전히 객체 생성 과정에 성능 부하가 있음이 파악됨 Pool에서 꺼내온 후 특정 조건에 따라 AddComponent 실행 하지만 데이터 및 코드를 추적해본 결과 100%의 객체가 같은 Component를 추가함 Pooling 할 때 미리 추가하게 변경 → 50% 이상 성능 개선
32. 자작툴 simplehelper 공유 https://github.com/ipkn/simplehelper (python 3.6 이상 필요) 테스트할 기기에 simpleperf 설치 및 실행 수집 오류시 자동 재실행 심볼용 파일 복사 분석 결과 확인 심볼 업로드 후 FlameGraph 생성 & 다운로드
33. simplehelper simpleperf path NDK의 simpleperf 위치 Bundle identifier 앱 이름 (com.Company.ProductName) Profile duration 몇 초간 측정할지 지정 Arch. 해당 폰의 CPU 아키텍처. 보통 arm.
34. simplehelper 사용법 1. 각 필드를 적절한 값으로 설정 2. [Start profiler] 버튼을 눌러 프로파일링을 시작: 지정한 시간 동안 수집됨 3. 해당 시간이 경과한 후 같은 폴더에 perf.data 파일이 생성됨 (실행 중 장애가 난 경우 다시 시도) 4. [Collect symbol files] 버튼을 누르면 앱과 관련된 심볼을 binary_cache 폴더에 수집 5. binary_cache 안의 libunity.so, libil2cpp.so 파일을 디버깅 심볼이 있는 버전으로 교체 (apk 만들 때 같이 생성된 zip 파일 안에 포함) 6. [Run simpleperf report gui] 버튼으로 텍스트 결과를 확인하거나 [Build Flamegraph] 버튼을 눌러 Flamegraph 차트를 확인 (Flamegraph 기능은 서버가 켜져 있어야 동작하며, 하루에 한번만 실행할 수 있게 제한됨)
35. Q/A AddComponent 수행시 오버헤드였음은 프로파일러의 어떤 지표를 통해서 확인이 돼었었나요? 프로파일링 결과 AddComponent 함수의 수행시간 비율이 전체 실행 시간 대비 높게 집계되었습니다. AddComponent 관련 콜스택을 확인한 후, 관련 Object Pool에 넣을때 미리 Component를 추가하는 버전을 만들어 테스트 하였을 때 실제로 성능이 크게 개선되는 것을 확인했습니다. 테스트를 통해서 해당 부분이 문제였음을 확인할 수 있었습니다.
36. Q/A Q1. 최신폰에서도 발견할 수 있는 문제였나요? Q2. iOS에서는 느리지 않은데 어떤 점 때문에 해당 기기만 특이하게 느린건가요? 작업 초반에는 특정 하드웨어 문제가 있을 가능성도 포함해서 살펴봤지만, 테스트 결과 해당 폰이 일정 성능 이하여서 발생한 문제였습니다. 비슷한 성능의 기기를 프로파일링 해보았을 때, 그 양상이 크게 차이나지 않았습니다.
37. Q/A 별도 빌드가 필요한가요? 프로파일링 후 결과를 확인하기 위해선 심볼이 필요합니다. 유니티의 경우 Development Mode 옵션을 켜고 빌드하면 관련 심볼이 생성됩니다.


반응형

loading