새로 넣은 이펙트가 어떤 기기에서만 안 나온다는 얘기가 있었다. CCSpriteFrameCache 에 plist 를 물리는 코드를 보니 몇 가지 조건에서 건너뛰게 돼 있었다. 어느 조건에 걸린 것인지는 알 수 없었다.
Table of contents
Open Table of contents
조용히 건너뛰고 있었다
건너뛰는 이유가 넷인데 전부 같은 값을 돌려주고 있었다.
if (name.empty()) return false;
if (m_loaded.count(name)) return false;
if (!isFileExist(name)) return false;
if (m_memoryUsed > MEMORY_LIMIT) return false;
부르는 쪽은 실패했다는 것만 알고 왜인지는 모른다. 조건이 넷인데 결과가 하나면 그 넷을 구분할 방법이 없다.
이유를 남겼다
각 조건에 CCLOG 를 붙이고 addSpriteFramesWithFile() 앞뒤를 찍었다. 문제가 난 기기에서 받아 보니 네 번째였다.
[Effect] 메모리 한도 초과: effect_boss.plist (사용 52428800 / 한도 52428800)
메모리가 적은 기기에서 한도에 걸린 것이었다. 파일이 없는 것도 아니고 코드가 잘못된 것도 아니었다.
숫자를 같이 넣은 것이 도움이 됐다. 한도 초과라는 말만 있으면 얼마나 넘었는지 모른다. 조금 넘었으면 한도를 조정하면 되고 많이 넘었으면 구조를 봐야 한다. 이번에는 딱 한도라서 조금만 조정하면 되는 상황이었다.
정상인 건너뜀과 문제인 건너뜀
넷은 성격이 달랐다. 이름이 비었으면 코드 문제이고 이미 로드됐으면 정상이며 파일이 없으면 자료 문제이고 메모리 한도는 환경 문제다.
이미 로드된 것까지 매번 찍히면 시끄럽다. 그때 판에는 CCLOG 하나뿐이라 수준이 없었다. kMaxLogLen 이 16킬로바이트라 길이 상한도 있다. 앞에 태그를 붙이고 개발 빌드에서만 정상 건너뜀을 찍게 해서 직접 나눴다. 전부 남기는 것과 아무것도 안 남기는 것 사이에 이 구분이 있어야 로그를 계속 보게 된다.
결과 값도 나눴다
로그만으로는 부르는 쪽이 판단할 수 없어서 돌려주는 값을 LoadResult 로 나눴다. LOAD_OK 와 LOAD_NO_MEMORY 와 LOAD_NO_FILE 이 각각 다른 뜻이다.
LoadResult r = EffectLoader::load(name);
if (r == LOAD_NO_MEMORY) {
EffectLoader::unloadUnused();
r = EffectLoader::load(name);
}
메모리 부족이면 덜 중요한 것을 내리고 다시 시도할 수 있다. 파일이 없으면 재시도해도 소용없으니 안 한다. 재시도해서 되는 것과 안 되는 것을 구분하려면 이유가 값으로 돌아와야 했다.
사용자에게도 알렸다. 메모리 부족으로 못 띄우면 설정에서 효과 수준을 낮추도록 안내한다. 아무 설명 없이 안 나오는 것보다 낫다.
정리
- 건너뛰는 조건이 여럿인데 결과가 하나면 왜 안 했는지 알 수 없다
- 각 조건에
CCLOG를 붙이면 문제가 난 환경의 로그로 바로 갈린다 - 판단에 필요한 숫자를 같이 남긴다
- 얼마나 넘었는지가 다음 행동을 정한다
- 로그 수준이 없으면 태그와 빌드 구분으로 직접 나눈다
- 결과 값을
LoadResult로 나누면 부르는 쪽이 행동을 정한다 - 재시도해서 되는 것과 안 되는 것을 구분한다
- 사용자가 겪는 증상이면 안내도 같이 한다