Android의 경우 Memory Usage를 측정할 때 많이 사용하는 명령어는 adb shell 명령어 중 하나인 dumpsys meminfo 입니다. dumpsys meminfo에 대해서는 다른 포스트를 이용하여 설명하기로 하고 이번에는 Linux에서 제공하는 Memory 확인 명령어인 "free" 와 "/proc/meminfo"에 대해 알아보도록 하겠습니다.
먼저 adb shell에서 간단하게 현재 시스템의 메모리 상태를 확인하려면 "free -m" (여기서 -m 옵션은 용량을 MB로 출력하라는 옵션입니다.)명령어를 입력하시면 됩니다. 그러면 아래와 같은 정보가 출력됩니다. 아래 내용을 보면 첫 줄의 값 중 used값인 3508이 사용 중인 메모리이고 free 값인 4173이 사용가능한 메모리로 생각되지만 이는 buffers와 cached에 대한 계산이 되지 않은 값입니다. 커널 내부적으로는 buffers와 cached의 경우 메모리가 부족할 때 언제든지 사용가능하다고 여기기 때문입니다. 그래서 좀더 자세한 값은 그아래 -/+ buffers/cache 구간에서 확인할수 있습니다.
$ free -m
total used free shared buffers
Mem: 7681 3508 4173 18 31
-/+ buffers/cache: 3476 4205
Swap: 4095 0 4095
각각의 column 정보의 의미는,
- total : system에서 사용되고 있는 총 메모리의 크기
- used : 사용 중인 메모리의 크기로 used = total - free - buffers - cached 로 계산됩니다.
- free : 사용되지 않는 메모리 크기
- shared : backward compatibility를 위해 보여지는 값으로 무시해도 됩니다.
- buff/cache : 커널 버퍼로 사용되는 메모리와 페이지 캐시와 slab을 합한 메모리 크기로 이 메모리는 애플리케이션이 필요할 때는 반환이 가능합니다.
- available : 애플리케이션이 시작할 때 swapping없이 사용가능한 메모리의 크기
실질적인 메모리 사용량을 계산하고 싶을 때는 -/+ buffers/cache row 의 used 나 free 값을 이용해서 계산하면 됩니다.
Memory Usage (%) = used / total * 100 = 3476 / 7681 * 100 = 45.254 (%)
adb shell 명령어인 free, top, ps 는 /pco/meminfo를 이용해서 메모리 정보를 출력하고 있습니다. 따라서 보다 자세한 메모리 정보를 확인하기 위해서는 /proc/meminfo를 이용하면 되고, adb shell 에서 "cat /proc/meminfo"를 하면 결과값을 얻을 수 있습니다.
[root@localhost]# cat /proc/meminfo MemTotal: 16325540 kB // 전체 메모리 크기 MemFree: 5912216 kB // 사용되지 않고 있는 메모리 크기 Buffers: 538596 kB // buffer_heads에 사용되는 메모리 크기 (ext* 파일시스템이라면 Buffers는 메모리에 저장되어 있는 메타데이터의 크기) Cached: 7945564 kB // 파일 데이터 캐시에 사용되는 메모리 크기 SwapCached: 3512 kB // 실제 메모리 상에 존재하는 swap 크기 Active: 4595420 kB // active 메모리 크기 Inactive: 4537624 kB // inactive 메모리 크기 (메모리 반환시 우선적으로 반환될 대상) Active(anon): 471856 kB // active 메모리 중 anonymous pages 크기 Inactive(anon): 183712 kB // inactive 메모리 중 anonymous pages 크기 Active(file): 4123564 kB // active 메모리 중 mmaped 할당된 크기 Inactive(file): 4353912 kB // inactive 메모리 중 mmaped 할당된 크기 Unevictable: 0 kB // swap out 할 수 없게 고정된 크기. 커널에서 고정시킨 page와 유저공간에서 Mlocked 된 page의 합 Mlocked: 0 kB // 유저공간에서 Mlocked로 고정된 page 크기 SwapTotal: 2096476 kB // 전체 swap 크기 SwapFree: 2063212 kB // swap 공간 중 사용가능한 공간 크기 Dirty: 316 kB // 페이지캐시 데이터 중 디스크에 쓰여지기 위해 대기 중인 크기 Writeback: 0 kB // 페이지캐시 데이터 중 현재 디스크에 쓰여지고 있지만 완전히 쓰여지지 않은 크기 AnonPages: 645448 kB // anonymous page의 전체 크기 Mapped: 87704 kB // mmaped로 할당된 페이지 크기. ex) 라이브러리 파일 Shmem: 6684 kB // shared memory 크기 Slab: 1071668 kB // 커널에 의해 할당된 크기 SReclaimable: 1018168 kB // 커널에 의해 할당된 것 중 반환가능 한 크기 SUnreclaim: 53500 kB // 커널에 의해 할당된 것 중 반환불가능한 크기 KernelStack: 3160 kB // 커널 stack에 할당된 크기 PageTables: 21876 kB // 시스템의 모든 페이지를 기록하기 위한 메모리 크기 NFS_Unstable: 0 kB // NFS 페이지 중 서버에 전송되었으나 storage에 커밋되지 않은 크기 Bounce: 0 kB // 블록 디바이스의 Bounce buffer 크기 WritebackTmp: 0 kB // FUSE에서 사용되는 writeback 크기 CommitLimit: 10259244 kB // 현재 시스템에 할당할 수 있는 메모리 사이즈 Committed_AS: 2779732 kB // 현재 시스템에 할당되어 있는 메모리 사이즈 VmallocTotal: 34359738367 kB // vmalloc으로 할당할 수 있는 전체 사이즈 VmallocUsed: 303652 kB // vmalloc으로 할당된 사이즈 VmallocChunk: 34359376640 kB // vmalloc으로 할당할 수 있는 가장 큰 연속된 블록의 크기 HardwareCorrupted: 0 kB AnonHugePages: 454656 kB // 유저 공간 페이지 테이블에 anonymous huge page로 할당된 크기 HugePages_Total: 0 // hugepages 관련 정보들 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB DirectMap4k: 7680 kB // direct mapping 사이즈 DirectMap2M: 16760832 kB 출처 : https://bloodguy.tistory.com/entry/Linux-시스템프로세스-메모리-사용량-확인-check-systemprocess-memory-usage |
참고로 출력된 meminfo 정보의 MemTotal 값을 보면 실제 RAM 값보다 더 적은 것을 알 수 있습니다. 이 MemTotal 값은 실제 물리적 메모리에서 커널코드와 일부 예약된 공간을 제외한 값으로 실제 RAM 값보다 더 적은 값으로 출력됩니다.
이 /proc/meminfo 정보를 이용해서 System의 Memory Usage를 계산하는 방법은 아래와 같습니다.
이 stackoverflow 에서 논의되는 내용을 보면 htop 코드를 기준으로 메모리 사용량을 계산할 수 있을 것 같습니다.
아래 github를 확인하면 메모리 사용량을 계산하는 소스코드를 확인할 수 있습니다.
즉, usedMem = MemTotal - MemFree - ( Buffers + ( Cached + SReclaimable - Shmem ) ) 로 계산됩니다.
static inline void LinuxProcessList_scanMemoryInfo(ProcessList* this) {
...
if (tryRead("MemTotal:", &this->totalMem)) {}
else if (tryRead("MemFree:", &this->freeMem)) {}
else if (tryRead("MemShared:", &this->sharedMem)) {}
if (tryRead("Buffers:", &this->buffersMem)) {}
if (tryRead("Cached:", &this->cachedMem)) {}
if (tryRead("Shmem:", &shmem)) {}
if (tryRead("SReclaimable:", &sreclaimable)) {}
...
this->usedMem = this->totalMem - this->freeMem;
this->cachedMem = this->cachedMem + sreclaimable - shmem;
this->usedSwap = this->totalSwap - swapFree;
}
void Platform_setMemoryValues(Meter* this) {
ProcessList* pl = (ProcessList*) this->pl;
long int usedMem = pl->usedMem;
long int buffersMem = pl->buffersMem;
long int cachedMem = pl->cachedMem;
usedMem -= buffersMem + cachedMem;
this->total = pl->totalMem;
this->values[0] = usedMem;
this->values[1] = buffersMem;
this->values[2] = cachedMem;
}
이는 아래 free 명령에 대한 man pages에서도 확인할 수 있습니다.
used Used memory (calculated as total - free - buffers - cache)
https://man7.org/linux/man-pages/man1/free.1.html
이를 기준으로 메모리 사용량을 계산하면 아래와 같습니다.
Used Memory = MemTotal - MemFree - (Buffers + (Cached + Sreclaimable - Shmem))= 16325540 - 5912216 - (538596+(7945564+1018168-6684)) = 917680
메모리 사용량(%) = Used Memory / Total Memory * 100 = 917680 / 16325540 * 100 = 5.62 (%)
※ 참고사이트
https://bloodguy.tistory.com/entry/Linux-시스템프로세스-메모리-사용량-확인-check-systemprocess-memory-usage
https://rednine.tistory.com/792
https://stackoverflow.com/questions/41224738/how-to-calculate-system-memory-usage-from-proc-meminfo-like-htop
https://stackoverflow.com/questions/41224738/how-to-calculate-system-memory-usage-from-proc-meminfo-like-htop
https://xinet.kr/?p=1528
https://zetawiki.com/wiki/%EB%A6%AC%EB%88%85%EC%8A%A4_%EB%A9%94%EB%AA%A8%EB%A6%AC_%EC%82%AC%EC%9A%A9%EB%A5%A0_%ED%99%95%EC%9D%B8
https://ssambback.tistory.com/entry/Linux-Memory%EC%9D%98-%EC%83%81%ED%83%9C%EB%A5%BC-%EB%B6%84%EC%84%9D%ED%95%98%EB%9D%BC
http://rousalome.egloos.com/v/9966593
https://stackoverflow.com/questions/1353283/what-does-the-linux-proc-meminfo-mapped-topic-mean
https://linuxize.com/post/check-memory-linux/
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/s2-proc-meminfo