안드로이드는 파면 팔수록 한숨이~... 메모리 관리의 심각한 문제점
2012.10.10 19:41
먼저, 규모있는 안드로이드 앱 개발자분들의 노고에 감사드립니다.
안드로이드 메모리 관리가.. 구석기시대보다 못하다는 소리가 있어서 뜯어봤더니
생각하던 것 보다 훨씬 심각하네요.
젤리빈이고 버터프로젝트고 나발이고, 메모리 구조부터 뜯어고치는게 가장 시급해 보입니다.
요즘 안드로이드 램이 2GB까지 올라갔고, 삼성은 3GB디바이스를 테스트중이라고 합니다.
곰곰히 생각해 보세요. 이거 좀 이상한겁니다.
제 노트북으로 별 희안한 짓거리를 다 하지만, 램은 2GB면 충분합니다.
엔드유저 입장에서는 데스크탑OS에서도 2GB면 할일 편하게 다 합니다.
윈도우7과 2GB램에서도 워드 띄우고, PDF리더 띄우고, 웹페이지 20개 띄우고, 비주얼스튜디오 띄우고, 음악 틀어두고, Dropbox실시간 동기되고, 백신프로그램이 2개나(V3, MSE) 백그라운드로 돌고, 아웃룩은 주기적으로 메일 체크하고...
이렇게 엄청난 작업을 동시에 진행함에도 2GB의 램은 부족하지 않습니다. (물론 스왑을 쓰니 가능한 것이긴 합니다.)
하지만 꼴랑 한두개 앱을 띄우는 안드로이드가 2GB램을 쓴다고 합니다.
이거 이상해도 심하게 이상합니다.
그래서 안드로이드 메모리 관리 부분을 좀 뜯어봤습니다.
결과는? 처참합니다.
2GB가 필요해서 달아둔게 아니라, 안드로이드 메모리 관리가 매우 엉망이라 2GB를 달았던 겁니다.
안드로이드 구조 상, 어차피 앱은 디바이스 램이 2GB는 200GB든.. 많아봐야 150MB정도밖에 쓸 수 없습니다.
디바이스의 램이 늘어난다는 것은, 앱의 가용램이 증가한다는 것을 의미해야 정상인데..
안드로이드는 가용램의 상한이 32MB~64MB~128MB~?MB입니다.
심각한 것은.. 가용램의 상한이 얼마인지는 아무도 모른다는 것.
앱 개발시 상한선과 하한선, 즉 메모리 바운더리를 모르는 것은 매우 위험합니다.
그런데 안드로이드에서는 그걸 알 수 없습니다. 이건 뭐 에니악(최초의 컴퓨터)인가?
그래서 널리 쓰이는 앱을 만드는 개발자는 가용램의 상한을 32MB로 두고 제작해야 안전합니다.
(꼼수로 JNI와 병행하면 더 쓸 수 있습니다. JNI는 Native힙을 씁니다.)
안드로이드의 메모리관리는 다음의 특징을 가집니다.
1. VM힙 사이즈의 최대치는 대체로 128MB이다. (32MB도 있고, 64MB도 흔함)
: 이 것은 앱이 사용할 수 있는 최대 메모리로 생각하시면 됩니다. 네.. 128MB밖에 안됩니다.
(비트맵은 별도일 수도 있으나, 디바이스마다 실행시점마다 다름)
2. VM힙 Growth Limit사이즈는 보통 48MB이다.
: 이 것은 VM힙의 가비지컬렉팅 스레숄드와 비슷합니다. 힙 사이즈가 이전 가비지컬렉팅 시점으로부터 48MB 증가하면 가비지 컬렉팅을 수행합니다. (안드로이드의 가비지컬렉팅 policy가 이렇습니다.)
3. Bitmap은 VM힙에 들어올 수도 있지만, Native힙에 들어갈 수도 있다.
: 안드로이드 OS가 임의로 어느 곳에 위치시킬지 판단합니다. 앞서 메모리 바운더리를 알 수 없는 것과 마찬가지로,
이러한 "불확실성"은 앱 개발에서 매우 치명적입니다.
보통은 Bitmap은 용량이 크기 때문에 VM힙에 들어가기 어려울 것이라 판단되면 Native힙에 넣습니다.
하지만 개발자는 사용자의 디바이스에서 이 비트맵이 VM힙에 들어갈지 Native힙에 들어갈지 추정이 불가능합니다.
4. [Important] 안드로이드 Native힙에 들어간 Bitmap은 메모리에서 다시 내려오지 않는다.. ㄷㄷㄷㄷㄷ
비트맵은 특성상 메모리 소모량이 매우 큽니다. 32-bit면 1픽셀당 무려 4바이트나 먹습니다.
(960x640사이즈라면 비트맵 사이즈만 21MB로 램을 차지합니다.)
그런데 안드로이드 커널은 Native힙에 들어간 Bitmap은 더 이상 사용하지 않더라도 메모리에서 다시 내려오지 않습니다.
엄청난 메모리 누수가 바로 여기서 발생하는듯 합니다.
일단 정보의 나열은 이러한데,
VM힙 Growth Limit와 VM힙 사이즈와, Bitmap은 VM힙에 들어갈지 Native힙에 들어갈지는 앱 러닝 시점에 따라 변경된다는 점이 맞물려서 아주 기이한 현상이 나타날 수 있습니다.
i.) 만약 비트맵이 VM힙에 들어갔는데, VM힙 Growth Limit을 넘어선다면?
가비지컬렉팅을 수행할 것입니다. 그런데 가비지컬렉팅은 반드시 시스템 전체가 정지된 상태에서 수행되어야 하므로 상당한 성능저하를 가져옵니다.
즉 이 부분에서 전체 시스템의 큰 성능저하가 나올 수 있습니다.
ii.) 또, 비트맵이 Native힙에 들어간다고 해도 문제입니다.
한번 메모리에 올라가면 다시 내려오지 않으니까요. -_- 메모리 낭비의 주 원인입니다.
앞선 예에서 보면 960x480은 비트맵만으로 21MB의 램을 차지합니다. 그런데 이게 메모리에서 안 내려옵니다. 정확히는 못 내립니다.
애니팡 로딩화면이 10장의 비트맵으로 구성되어 있다면, 210MB의 램을 요구할 것입니다. 하지만 로딩이 끝나도 이 210MB는 여전히 차지하고 있습니다.
그러니 디바이스 램이 2GB씩이나 필요하게 됩니다.......
쉽게 말해서, 똥을 싸도 물을 못 내리니 변기가 2000개씩 필요한 상황이라 보시면 됩니다.
한마디로 요약하면 안드로이드 메모리 관리는 총체적 난국입니다.
포기하면 편할 듯 -_- 엉망진창이네요.
ps. CM(CyanogenMod)롬을 사용하거나 CM커널을 사용하면 "Allow Purging Assets"옵션이 있습니다.
이 옵션은 Native힙에 올라간 비트맵이 더 이상 사용되지 않으면, 메모리에서 내려주는 역할을 수행합니다. 아주 유용한 기능이죠.
CM을 사용하신다면 이 기능을 "꼭" 사용하시기 바랍니다.
또한 CM의 KSM(Kernel Samepage Merging)도 적용하면 좋습니다. 이 부분도 사실 안드로이드 커널이 병맛이라 -_- CM에서 끼워둔 것인데, 안드로이드의 공용코드가 중복해서 메모리에 올라오기때문에 누수가 생깁니다. (앱을 많이 써도 수MB~수십MB수준이라 큰 부분은 아닙니다.)
그런데 KSM을 사용하면 이러한 '공용코드'에 대해서는 동일한 메모리를 참조하도록 하므로 메모리 사용량을 줄일 수 있습니다.
참고로 Allow Purging Assets와 KSM(Kernel Samepage Merging)은 모두 CPU 자원을 소모합니다. 즉 약간 느려집니다.
그런데 체감할 정도의 차이는 아니니 그냥 체크하시는게 좋습니다.
구글은 안드로이드 메모리 관리를 도저히 수정할 생각이 없는 듯 하니..
가급적 CM이 사용가능한 안드로이드 디바이스를 구입하시는 것이 좋을 것 같습니다. (아니면 아이폰을 쓰세요.)
ps. 역시 운영체제 구조, 구현, 성능은 iOS가 짱인 듯. 어쩌면 안드로이드가 너무 비상식적으로 엉망일지도.
ps. 안드로이드는 본래 블랙베리OS처럼 메모리 소모량이 적은 "텍스트기반 앱"지원을 위해 설계된 OS라 환경이 이따구입니다. 텍스트기반 앱 사용에는 이러한 구조가 효율적일 수 있습니다. 하지만 안드로이드는 비트맵이 난무하는 OS라는게 문제이고, 지금 안드로이드의 메모리 구조로는 2GB램은 나발이고 4GB램을 달고 나와도 항상 램이 부족하다는 소리가 나올 것입니다. 어차피 앱에서 Bitmap을 제외한 램은 VM힙 사이즈 제한으로 인해 128MB도 못 씁니다.
코멘트 30
-
스파르타
10.10 19:53
-
piloteer
10.10 19:56
오픈소스에는 죄가 없습니다. 안드로이드 설계 사상이 지금같은 상황을 고려하지 못한 것이겠지요. 거기에 버전업할때 이런 부분을 안 고치는 게 문제인 거지요.
오픈소스중에는 좋은 프로그램들이 많습니다.
-
스파르타
10.10 20:07
오픈OS 이기 때문에 관리가 안돼는 것처럼 보여서요 ㅎㅎ 물론 장점도 있지만 APP등 여러 가지 때문에 조금 그러한 면들있어요
-
piloteer
10.10 20:19
오픈OS가 오픈 플랫폼을 말씀하시는 거라면 Mac vs PC같은 상황이니 어쩔 수 없고, 오픈소스로서의 품질관리를 말하자면 오픈소스 기반 소프트웨어들중에 품질 관리가 잘 되는 물건들도 꽤 있다는 뜻입니다. 예를 들어 BSD계열 운영체제 같은 경우 일반인이 다루기 힘들지는 몰라도 참 안정적이고 포팅도 잘 되고 맥OSX에도 들어갔지요. 리눅스도 일반 PC운영체제로 쓰면 배포판이 난립해서 그렇지 커널 자체는 안정적이고 성능도 괜찮고 말이지요. 적어도 안드로이드가 보이는 리소스관리문제같은 걸 볼 일은 잘 없습니다.
요즘은 어중간한 상용코드들보다 오픈소스가 품질이 나은 경우가 꽤 있죠. 문서화나 편의성이 좀 뒤지는 경우는 있어도 말이죠.
-
스파르타
10.10 21:03
ㅎㅎ 친절한 설명 감사드립니다~!
-
해적
10.10 19:57
cm을 애용하라~ 알겠습니다~ -
정화니
10.10 20:01
감사합니다. 한번 적용해봐야겠네요. -
matsal
10.10 20:28
그 노트북 해상도는 쓰시는 폰보다 떨어질 겁니다 ㅎㅎ
-
에스비
10.10 20:45
노트북 해상도가 1680*1050인데 이보다 해상도가 높은 안드로이드폰이 있나요?
-
matsal
10.10 22:32
1920x1080 은 꽤 있고
2560x1600 도 타블렛으로 나온다거나 할 겁니다.
지금 저는 1920x1080 짜리 22인치 타블렛 기다리고 있고요.
-
에스비
10.10 22:37
폰은 1080이 나올 예정인건 있으나 아직 나온건 없네요. 이 글의 수치는 폰 기준입니다. -
스카이워커
10.10 20:30
UI 스레드 처리도 그렇고, (심각하게) 부족한 설계를 computation power로 뭉개는 방법을 취할 수 밖에 없는 상황이군요.
힘내라 Windows Phone 8...
-
윤발이
10.10 20:57
2.2 지나서는 오오 안드로이드 많이 괜찮아 졌어.. 라고 생각 했는데..
2.3 넘어 ICS 부터.. 어 뭔가 좀.. 하더니 오히려 점점 더 안좋아 지고 있는것 같기도 합니다 -_-;
-
Pinkkit
10.10 21:13
태생적인 한계 + 구글의 무책임함(?) 이 만들어낸 합작품이 아닐까 합니다.
애초에 안드로이드 초기 단계에서 스마트폰이 이만큼이나 발전할거라는 예측을 하지 못했기 때문이겠죠.
차라리 웹OS가 훨씬 더 미래를 내다본 OS라고 생각하는데, 결국 사장되어버린걸 보면 뭔가 아이러니 하기도 합니다.
오픈소스로 화려하게 부활했으면 좋겠네요.
-
sjlee
10.11 09:16
더 좋은 기술, 제품이 사장되는 경우 많이 있는 것 같습니다. 안타깝죠.
-
egregory
10.10 22:04
native bitmap클래스를 말씀하시는 것인지요?..
native heap을 사용하여 수십개 png 메모리를 처리해서 OpenGL로 올리고
heap 풀고 해도 이부분은 괜찮았었는데요..
-
egregory
10.10 22:08
다시 보니 NDK에 대한 얘기가 아니군요..
NDK로 가야죠 무조건..
대형 android 프로그램에서 자바는 껍데기랑 네트워크,사운드용이죠
-
에스비
10.10 22:40
(나온지 얼마 되지도 않았지만)NDK 사용을 억제하는 모습이 보여서 무조건 NDK만을 사용하기도 애매합니다.
현재로선 말씀하신 것과 같이 NDK를 쓰는 것 외엔 대처할 방도가 없어 보입니다. -
calm
10.10 23:46
오.. 한 번 네이티브에 올라가면 계속 남아 있는건가요? 리부팅 시킬 때 까지 --? 대단한데요 그건;;
-
piloteer
10.11 00:09
아마 해당 테스크를 킬할때까지가 아닐까 싶습니다. C로 치자면 delete가 안되는 그런...
진짜로 계속 남아있는다면 메모리관리가 너무 안될 거 같네요...
-
purity
10.11 00:05
버전에 따라 갈리기는 합니다만 해상도별 레퍼런스도 있고 최대 한계치를 얼추 구할 수 있으니 완전히 투명하지는 못해도 OOME가 안드로이드 메모리 매니징의 문제로 바로 귀결되는 것은 무리지 않을까요? GC의 경우도 점차 개선되어 있어서 부하를 준다고는 하지만 일단은 concurrent로 발전했고 bitmap의 경우에도 recycle을 정확하게 하지 않았거나 앱이 서비스 형태를 너무 지향하거나 스레드 만들어 놓고 뒷감당 하지 않아 프로세스가 살아있기에 남겨지는 경우가 많은게 아닐까 싶습니다.
또한 Rich 한 인터페이스와 고해상도 등에 대응하기 위해서 발전해야 하는 것은 분명하지만, 안드로이드가 쉬운 접근으로 표준 UI 컴포넌트를 이용해서 데스크탑 코딩 감각으로 신속하게 앱을 개발하려는 의도를 가지고는 있으나 근본은 엠베디드와 모바일이라는 것도 개발자가 잊지 말아야 할 부분인 것 같습니다. 예로 코드 습관만 보아도 GC까지의 한계도 크고 부하도 적어 indent나 잘하라며 무시당하는 '바른 코딩'들의 비중이 커지니까요.
따지고 보면 16MB~48MB는 크다면 매우 큰 메모리이고 많은 어플리케이션이 개발 되기에 충분한 환경이 아닐까도 싶은데... 요즘 트렌드는 마치 웹에서 디자이너가 dreamweaver로 잘라준 덩어리 큰 이미지 가득한 html위에 자바스크립트 코딩하는 것과 비슷하게 보이는(보이는 것이지 내부는 다르겠지요) 움찔하게 화려한 앱들이 많은 듯 해요. 기능에 비해 '이렇게나 화려할 필요가 있나?' 싶은 앱을 자주 대한다고나 할까요? 간단한 것을 좋아하는 제 취향이 잘못된 것인가 싶기도 하고 말이지요. 취향이 이상한건가...음...
아... 그리고 역시 NDK가 있으니 ㅎㅎ;;;
-
Lusiyan
10.11 00:13
진짜 안드는 기기 성능빨로 밀어붙이는 느낌이 팍팍....
P.s 힘내라 윈폰...
-
왕초보
10.11 01:36
그래서 그런지 역시 트레오가 짱. ( '')
-
midday
10.11 21:55
팜에서 개발하면 머리 쥐어뜯어요~ 이건 뭐 메모리 절약대회에 나가는것도 아니고 ;;;
-
맑은샛별
10.11 02:19
안드로이드는 약간 불안정하다는 느낌도 있어요.
버벅이는 것도 그렇고.... 먹통되는 증상도... 이유없는 재부팅도.... -_-
-
왕초보
10.11 05:46
그 점은 iOS도 별 차이 없어요. 차라리 이유없이 재부팅이라도 해주면 다행이죠. 그냥 먹통.. 터치는 먹는데 아무것도 안되는. 운 좋으면 껐다가 키면 되지만 가끔은 하드리셋. ㅠㅜ
-
시월사일
10.11 10:40
이전에 IOS가 훨씬 쾌적하고 좋았지만
업데이트할수록 IOS도 버그가 많아지는 듯 합니다.
(안드로이드는... 구글에서 대대적으로 고치거나 능력자가 커스텀으로 만들어내지않으면 답없어보입니다;)
윈모가 힘냈으면 좋겠지만... 별 희망이없어보여요ㅠㅠ
-
사모쓰
10.11 11:25
이 글을 보니 왜 자꾸 불필요하고 사용 중지된 Task가 자꾸 남는지 조금 이해하게 되었습니다.
좋은 글 감사드립니다~
멀티 태스킹해도 2개 정도 어플을 돌리는데 왜 이렇게 램이 부족한지 의아했던 참이었지요;;;
-
하뷔
10.11 11:29
그래서 저는 주기적으로 리붓하고 있지요. 대충 감은 잡고 있었지만 이정도일줄이야.
-
RuBisCO
10.25 20:05
잘못된 내용입니다. 링크 참조부탁드립니다.
http://dalinaum-kr.tumblr.com/post/34289540794/misunderstanding-android-memory-management
쩝.... 어쩔수 없는 거 같아요OPEN OS ? 이다보니 발적화 신공만 늘어나는거 같은 기분에다....