본문 바로가기

IT

iOS와 다르게 안드로이드는 왜 항상 램이 부족한가??.txt




안드로이드 메모리 관리가.. 구석기시대보다 못하다는 소리가 있어서 뜯어봤더니

생각하던 것 보다 훨씬 심각하네요.


젤리빈이고 버터프로젝트고 나발이고, 메모리 구조부터 뜯어고치는게 가장 시급해 보입니다.




요즘 안드로이드 램이 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도 못 씁니다.




---------------------------------------------------------------------------------------------



본문 한 줄 요약


: "쉽게 말해서, 변기 물을 못 내리니 변기가 2000개씩 필요한 상황이라 보시면 됩니다."


'IT' 카테고리의 다른 글

애플 수집가[BGM]  (0) 2012.04.13
대한민국 후덜덜한 IT 인맥도[BGM]  (0) 2012.04.06
전설의 해커들  (0) 2012.03.18
3DP Chip 드라이브 자동설치 프로그램  (0) 2012.02.05
스마트114 분석과 리뷰분석  (0) 2012.02.03