Cocos2d-x 로 만든 앱을 처음 켜면 몇 초 멈췄다. 어떤 Android 기기에서는 아예 죽었다.
Table of contents
Open Table of contents
시작 자리에 다 붙어 있었다
AppDelegate 의 시작 함수에 여섯 가지가 붙어 있었다. UserDefault.xml 을 읽는다. 텍스처를 전부 올린다. 소리도 전부 올린다. 그리고 서버에 두 번 붙는다.
이게 다 메인 스레드다. Android 는 입력에 5 초 넘게 응답이 없으면 ANR 로 죽인다.
GameData::getInstance()->load();
ResourceLoader::loadAll();
SoundManager::getInstance()->preload();
NetworkClient::checkVersion();
NetworkClient::sendInstallLog();
첫 실행에서는 UserDefault.xml 이 없어서 만든다. 텍스처도 CCTextureCache 에 없어서 전부 읽는다. 두 번째부터 빠른 것이 이 때문이고, 그래서 개발 중에는 이 상태를 잘 안 만난다.
각 줄의 시간을 쟀다
무엇이 오래 걸리는지 짐작하지 않고 줄마다 CCLOG 로 시간을 찍었다.
load() 31 ms
loadAll() 2,840 ms
preload() 410 ms
checkVersion() 920 ms
sendInstallLog() 880 ms
텍스처 올리는 것이 대부분이었다. HTTP 두 개가 각각 1 초 가까이 걸렸다. 재 보기 전에는 여섯 줄이 다 비슷하게 무거워 보였다.
지금 필요한 것만 먼저 했다
첫 화면에 나오는 텍스처는 몇 개 안 된다. 그것만 올리고 나머지는 화면이 뜬 뒤로 미뤘다.
ResourceLoader::loadForScene("title");
2,840 밀리초가 240 밀리초가 됐다. 나머지는 CCTextureCache 의 addImageAsync 로 뒤에서 올린다. 다 올라오면 셀렉터가 불린다.
네트워크도 나눴다. 버전 확인은 결과를 기다려야 하지만 설치 기록은 기다릴 이유가 없다. 기다려야 하는 것과 안 기다려도 되는 것을 시작 자리에 같이 두면 둘 다 기다리게 된다.
돌아온 값을 안 보고 있던 것도 고쳤다. 비행기 모드에서 켜도 그냥 넘어가긴 했는데 그건 우연이었다. 되는 경우와 안 되는 경우를 다 적었다.
첫 실행의 재현과 실패 뒤
두 번째부터는 캐시가 있어 빠르니 첫 실행을 일부러 만들어야 했다.
$ adb shell pm clear <패키지>
$ adb shell am start -n <패키지>/.MainActivity
pm clear 는 설정에서 데이터 지우기를 누른 것과 같다. 안 먹는 기기에서는 adb uninstall 뒤에 다시 깔았다.
지우고 켜는 것을 확인 절차에 넣었다. 기기 다섯 대에서 돌려 보니 한 대가 여전히 느렸다. 저장 공간이 거의 차 있는 기기였다.
첫 실행 중간에 죽으면 다음에 어떻게 되는지도 봤다. 쓰다 만 UserDefault.xml 이 남으면 libxml2 가 그걸 읽다가 또 죽는다. 온전한지 보고 아니면 새로 만들게 했다. 한 번 죽으면 계속 죽는 것이 제일 나쁘다.
정리
- 시작하는 자리에 일을 다 붙이면 첫 실행에서 한꺼번에 일어난다
- 짐작하지 말고 각 줄의 시간을 잰다
- 재 보기 전에는 전부 비슷하게 무거워 보인다
- 첫 화면에 필요한 것만 먼저 올리고 나머지는
addImageAsync로 올린다 - 시작 자리는 메인 스레드다. 5 초를 넘기면 ANR 로 죽는다
- 기다려야 하는 것과 안 기다려도 되는 것을 나눈다
- 돌아온 값을 본다. 안 보면 되는 경우와 안 되는 경우가 같아진다
- 첫 실행을 실제로 만들어 확인한다
- 중간에 죽었을 때 다음 실행을 생각한다. 계속 죽는 것이 제일 나쁘다