댓글 쓰기 권한이 없습니다. 로그인 하시겠습니까?
Android
2012.09.03 09:55
안드로이드 어플리케이션의 메모리 사용량을 확인하는 방법
조회 수 30582 댓글 0
How to discover memory usage of my application in Android 오랜만에 블로그에 포스트를 남기고 있습니다.
안드로이드 개발자 블로그에서 몇 가지 재미있는 글들이 올라왔는데, 그 중에 실재 안드로이드 팀의 엔지니어 한명이 안드로이드 프로세스의 메모리
사용 정보를 확인하는 방법에 관한 글을 링크한 내용이 있더군요. 개인적으로 관심이 가는 내용이기에, 해당 링크 (stackoverflow 에
답변으로 올렸더군요.)의 내용을 번역해 보았습니다. PS.그간의 근황에 관해서는 간단하게 잡담란에 이야기를 할 예정입니다.... (뭐 별거 없이
SC2 한 이야기이지요...)
리눅스와 같은 요즘 시대의 OS 상에서 한 어플리케이션이
어떻게 메모리를 사용하고 있는지를 확인하는 것은 이해하기에 어마어마하게 복잡하고 어려운 일입니다. 사실, 여러분이 확인 할 수 있는 여러
숫자들의 의미를 정학하게 파악하는 일은 거의 불가능에 가깝습니다. (다른 개발자들과 메모리 사용에 관한 여러 수치들을 놓고 이야기를 나누게
되면, 별다른 결론도 없으면서 길고 길게 이어지는 토론으로 끝날때가 많습니다.) 따라서, 우선적으로 안드로이드에서 대략 어떤식으로 메모리가 관리되는지에 관해 설명된 다음 글의 마지막
단락을 읽어 보시면 좋습니다.
(번역: http://huewu.blog.me/110081442947) 현재 안드로이드에서는 전체적인 메모리 상황을 살펴볼 기 위한 가장 최상위 API 는 ActivityManager.getMemoryInfo() 입니다. 이 메서드는 어플리케이션이 시스템이 현재 어느 정도의 메모리 여유를 갖고 있는지, 시스템 메모리 부족으로 인하여 서비스와 같은 백그라운드 프로세스 종료 등의 작업이 어느 시점에 일어날지에 관한 예측을 할 수 있도록 도와줍니다. 하지만, 순수한 자바 어플리케이션에서는 이 메서드는 사용할 필요가 별로 없습니다. 왜냐하면 자바 힙 메모리에는 제한이 걸려 있음으로(주>제가 알기로는 16메가 정도...) 하나의 어플리케이션이 시스템 전체 메모리에 부하를 주는 일을 방지하는 역할을 수행하기 때문입니다. 조금더 하위 레벨로 내려가보면, 메모리 사용에 관한 커널 레벨의 정보를 얻기위하여 Debug API 를 사용할 수 있습니다. http://developer.android.com/intl/de/reference/android/os/Debug.html 안드로이드 2.0 이후부터는 자신이 아닌 다른 프로세스의 메모리 정보를 얻기 위한 ActivityManager.getProcessMemoryInfo 메서드가 추가되었습니다. http://developer.android.com/reference/android/app/ActivityManager.html#getProcessMemoryInfo(int[]) 결과로 반환되는 MemoryInfo 구조체에는 아래와 같은 정보가 포함되어 있습니다.
하지만 도데체 "Proportional Set Size", "PrivateDirty", "SharedDirty" 이 것들은 무슨 뜻이고, 무슨 차이점이 있는 걸까요? 바로 여기서 부터 몇 가지 재미있는 이야기가 시작됩니다. 안드로이드(그리고 일반적인 리눅스)상에서 실재로는 서로 다른 프로세스가 메모리의 많은 부분을 공유해서 사용합니다. 따라서, 하나의 프로세스가 실재 얼만큼의 메모리를 사용하고 있는가는 명확하지 않습니다. 더군다나 메모리 페이지 영역을 디스크에 저장하는 경우를 추가해 생각해 보면 더더욱 명확하지 않습니다. 그러므로, 만일 여러분이 각각의 프로세스가 매핑하고 있는 실재 메모리 영역을 모두 더해보면, 아마도 여러분의 실재 RAM 크기보다 훨씬 큰 값을 얻게 될 것입니다. PSS 는 프로세스간에 공유된 메모리를 고려하여 커널이 계산한 수치입니다. 하나의 메모리 페이지 영역에 관하여, 해당 페이지를 공유하는 프로스세의 수를 기반으로 해당 메모리 영역을 나누어 메모리 사용량을 계산합니다. 이러한 방식을 통해 (이론적으로는) 모든 프로세스들의 PSS 값을 더하면 전체 프로세스가 사용하는 총 RAM 사이즈를 알 수 있습니다. 그리고 프로세스간의 PSS 값을 비교해보면 상대적으로 어떤 프로세스가 어느정도의 메모리를 사용하는지 대략적인 상황을 확인 할 수 있습니다. PrivateDirty 도 재미있는 수치입니다. 이 수치는 프로세스에 할당된 RAM 중에, 디스크로 저장될 수 없으며(메모리가 부족할 경우 디스크를 가상 메모리처럼 사용할 수 없음), 다른 프로세스와 공유될 수 없는 공간을 기반으로 계산됩니다. 이 수치는 해당 프로세스가 종료되었을 때 순수하게 시스템이 확보할 수 있는 메모리 공간이 어느정도 되는지를 확인하는 의미로 사용될 수 있습니다. ADB 를 이용하여, 현재 동작중인 시스템의 메모리 사용에 관해 더 많은 정보를 확인 할 수 있습니다. 이 때 사용되는 일반적인 명령어 중 하나는 "adb shell dumpsys meminfo" 입니다. 이 명령어는 각각의 자바 프로세스가 사용중인 메모리에 관한 정보를 쏟아내는데, 위에 설명한 내용 외에도 다양한 내용이 포함되어 있습니다. 또한 여러분은 특정 프로세스의 PID 나 프로세스 이름을 이용하여 해당 프로세스의 메모리 사용에 관한 정보를 추적할 수도 있습니다. 예를들어, 시스템 프로세스에 관하여 다음과 같은 결과가 출력되었다고 합시다. ** MEMINFO in pid 890 [system] ** native dalvik other total size: 10940 7047 N/A 17987 allocated: 8943 5516 N/A 14459 free: 336 1531 N/A 1867 (Pss): 4585 9282 11916 25783 (shared dirty): 2184 3596 916 6696 (priv dirty): 4504 5956 7456 17916 Objects Views: 149 ViewRoots: 4 AppContexts: 13 Activities: 0 Assets: 4 AssetManagers: 4 Local Binders: 141 Proxy Binders: 158 Death Recipients: 49 OpenSSL Sockets: 0 SQL heap: 205 dbFiles: 0 numPagers: 0 inactivePageKB: 0 activePageKB: 0 가장 위에 "size" 항목은 이 프로세스에 할당된 전체 힙 영역의 크기를 나타내며, "allocated" 는 실재로 사용중인 힙 영역의 크기를 "free" 는 아직 할당되지 않은 힙 영역의 크기를 나타냅니다. 이 때 사용되는 단위는 KB 입니다. "pss" 와 "priv dirty" 는 앞서 설명한 내용과 동일합니다. 만일 여러분의 전체 프로세스의 메모리 사용에 관한 정보를 알고 싶다면 "adb shell procrank" 명령어를 사용할 수 있습니다. 해당 명령어를 사용하면 아래와 유사한 결과를 확인 할 수 있습니다. PID Vss Rss Pss Uss cmdline 890 84456K 48668K 25850K 21284K system_server 1231 50748K 39088K 17587K 13792K com.android.launcher2 947 34488K 28528K 10834K 9308K com.android.wallpaper 987 26964K 26956K 8751K 7308K com.google.process.gapps 954 24300K 24296K 6249K 4824K com.android.phone 948 23020K 23016K 5864K 4748K com.android.inputmethod.latin 888 25728K 25724K 5774K 3668K zygote 977 24100K 24096K 5667K 4340K android.process.acore ... 59 336K 332K 99K 92K /system/bin/installd 60 396K 392K 93K 84K /system/bin/keystore 51 280K 276K 74K 68K /system/bin/servicemanager 54 256K 252K 69K 64K /system/bin/debuggerd 여기서 확인 할 수 있는 정보 중에 Vss 와 Rss 항목은 실재로는 전혀 쓸모가 없습니다. (이것들은 하나의 프로세스가 사용중인 RAM 영역의 크기를 직접 표시한 값인데, 공유된 메모리에 관한 고려가 없기 때문에 만일 이 값들을 모두 더해 본다면 실재 RAM 영역보다 훨씬 큰 값을 얻게 될 것입니다.) Pss 는 앞서 설명한 값이며, Uss 는 Priv Dirty 를 의미하며 이 역시 앞서 설명한 내용입니다. 여기서 재미있는 점은 Pss 와 Uss 의 값이 우리가 meminfo 명령어를 통해 살펴본 내용과 조금 (혹은 조금 보다는 좀 더 많이) 다르다는 점 입니다. 왜 그럴까요? 흠. procrank 는 데이타를 모으는데 meminfo 와는 조금 다른 커널 메커니즘을 사용하기 때문에 그렇습니다. 왜 서로 다른 메카니즘을 사용할까요? 솔직히 말해 저도 잘 모르겠습니다. 개인적으로 prorcrank 가 좀더 정확하다고 믿고 있습니다만, 사실 별 상관은 없습니다. 대충 가감하여 두 값중에 원하는 값을 취하시면 됩니다. 마지막으로 시스템의 전반적인 메모리 사용량을 요약하여 살펴보기 위하여 "adb shell cat /proc/meminfo" 명령어를 사용할 수 있습니다. 굉장히 많은 데이터가 출력되겠지만, 첫 부분의 몇줄만 이야기할 가치가 있습니다. (나머지 내용들은 오직 소수의 사람들만이 이해할 수 있으며, 제가 그 소수에 사람들에게 관련된 내용을 질문해 보았지만 그 답이 늘 일정하지 않더군요.) MemTotal: 395144 kB MemFree: 184936 kB Buffers: 880 kB Cached: 84104 kB SwapCached: 0 kB MemTotal 은 실재 커널과 유저 스페이스에 사용 가능한 메모리 총량으로 일반적으로 실재 물리적인 RAM 크기보다는 작습니다. (RAM 의 일부분은 라디오나 DMA 버퍼등으로 사용되기 때문입니다.) MemFree 는 전혀 사용되고 있지 않은 RAM 크기입니다. 여기 예시에 나온 수치는 매우 크지만, 일반적인 안드로이드 시스템에서 이 수치는 고작해야 몇 MB 에 그칠 것 입니다. 안드로이드는 메모리에 여유가 있는한 최대한 프로세스를 동작시키는데 사용하고자 노력하기 때문입니다. Cached 는 파일 시스템이 캐쉬나 다른 일들을 위하여 사용하는 메모리 크기입니다. 일반적으로 안드로이드 시스템은 "Bad Paging State" 로 빠지는 것을 방지하기 위하여, 20MB 정도의 Cashed 영역을 필요로 합니다. 안드로이드의 메모리 킬러(메모리가 부족할 경우 백그라운드 프로세스를 종료시키는 모듈)는 백그라운드 포르세스가 Cached RAM 을 너무 많이 소비하기 전에 해당 프로세스를 종료시키는 방식으로 작동합니다.
Dreamy의 코드 스크랩내가 모으고 내가 보는
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Designed by sketchbooks.co.kr / sketchbook5 board skin
Sketchbook5, 스케치북5
Sketchbook5, 스케치북5
Sketchbook5, 스케치북5
Sketchbook5, 스케치북5