리눅스 free 메모리의이해 엑셈컨설팅본부 /DB 컨설팅팀임경석 개요 리눅스환경에서메모리사용률을모니터링하기위해명령어를실행하다보면시스템을기동한지얼마되지않아 free 영역의지표가급격히줄어드는것을쉽게확인할수있다. 리눅스어드민경험이있는사람이라면이것이무엇을의미하는지알수있지만그렇지않을경우흔히들메모리사용률이높다고판단할수있다. 따라서, 결과로보여주는지표들이의미하는바를정확히이해하지못할경우잘못된판단을할수있다. 이번문서에서는리눅스에서메모리사용률을모니터링하는방법과각각의지표가의미하는바는무엇인지간단히살펴보기로하자. free 메모리의의미? 유닉스계열의시스템에서메모리사용률을확인하기위해 top, free, vmstat, sar, topas 등의명령어를주로사용한다. 리눅스에서는단순히 free 명령어를실행하면현재시점의메모리상태를쉽게확인할수있다. 필자의테스트장비는오라클리눅스 2.6-64bit 에오라클 11.2.0.3 버젼으로시스템을기동하자마다 free 를실행하면아래와같은결과를확인할수있다. Mem: 2002 325 1676 0 22 124 -/+ buffers/cache: 179 1823 전체메모리크기는 2,002 MB 이고, 서버가기동되면서사용된메모리는 325 MB, 여유메모리는 1,676 MB 이다. 여기서한가지주의해서볼것은각각 22 MB, 124 MB 로표시되는 buffers 와 cached 부분이다. 이미단어의의미에서유추해볼수있듯이 buffers 는메모리에존재하는데이터영역중디스크로플러시될데이타영역을의미한다. 흔히더티페이지로표현 216 2013 기술백서 White Paper
되는데이타구조나청크의개념이들어가있는메모리가여기에속한다. buffers 는주기적으로 bdflush 데몬에의해서디스크로플러시된다. 임의로플러시하기원한다면 sync 명령어를실행하면되는데이럴경우 buffers 에서더티페이지크기만큼만플러시된다. 현재더티페이지크기는 /proc/meminfo 의 Dirty 라고표시된부분을통해확인할수있다. 반면 cached 는기존에실행된프로그램들이사용했던메모리로실행중이거나새로시작될프로그램들이필요시빠르게재사용할수있는메모리영역을의미한다. 흔히디스크캐시라고도하는데, 캐시를유지하는이유는동일한데이터를요구하는프로그램이있을경우디스크로부터다시읽어들이는것보다는캐시된데이터를읽는것이성능에유리하기때문이다. 따라서, Cached 영역은실행중인프로그램이메모리가필요할경우바로사용되어지는 free 메모리라고생각할수있다. 유닉스계열의시스템에서메모리사용은크게프로세스가사용하는 heap 영역과디스크캐시영역으로나눌수있다. aix 의경우대부분의메모리를디스크캐시에할당한다. 따라서, 일정시간이경과하면 free 메모리가감소하는것을볼수있다. 리눅스의경우도마찬가지이다. cached 영역에 page cache 뿐아니라파일의자료구조인 inode 와 dentry 정보를저장하여 cached 영역이증가할수록 free 영역은감소하게된다. 그러나, 실제메모리의여유가없는것은아니고커널이필요할때마다 cached 영역을알아서조정하게된다. inode 와 dentry 는빠른데이터접근을위해필요한것인데, 커널의자원할당자역할을하는 slab allocator 라는것에의해서저장된다. cached 영역에서 slab 이차지하는영역의크기는 /proc/meminfo 를통해확인할수있다. [root@ora11 ~]# cat /proc/meminfo MemTotal: 2050780 kb MemFree: 1715904 kb Buffers: 22736 kb Cached: 128476 kb SwapCached: 0 kb Active: 91416 kb Inactive: 120960 kb Active(anon): 61416 kb Inactive(anon): 1188 kb Active(file): 30000 kb Inactive(file): 119772 kb Unevictable: 0 kb Mlocked: 0 kb Part 1 ORACLE 217
SwapTotal: SwapFree: Dirty: Writeback: AnonPages: Mapped: Shmem: Slab: SReclaimable: SUnreclaim: 3936248 kb 3936248 kb 52 kb 0 kb 61288 kb 32596 kb 1440 kb 92012 kb 18520 kb 73492 kb 모니터링 지금까지의내용을정리하면리눅스의경우메모리실제사용률을구하기위해서는실제 free 크기는 free 영역에 buffers 와 cached 를더하여계산해야한다는것이다. 이를토대로실제 free 와 used 크기를구하게되면 -/+ buffers/cache: 에표시된값과거의 일치한다는것을알수있다. Mem: 2002 325 1676 0 22 124 -/+ buffers/cache: 179 1823 전체메모리 total = used + free + buffers + cached 실제 free 메모리 = free + buffers + cached = 1676 + 22 + 124 = 1822 실제메모리사용량 = total-(free + buffers + cached) = 2002-(1676 + 22 + 124) = 179 이상태에서오라클을기동하면메모리사용량은어떻게변하는지살펴보자. SQL> startup ORACLE instance started. Total System Global Area 1068937216 bytes Fixed Size 2235208 bytes Variable Size 281019576 bytes 218 2013 기술백서 White Paper
Database Buffers Redo Buffers Database mounted. Database opened. 780140544 bytes 5541888 bytes [oracle@ora11 ~]$ free -m Mem: 2002 733 1268 0 53 416 -/+ buffers/cache: 263 1738 [root@ora11 ~]# ipcs -m ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 0 gdm 600 393216 2 dest 0x00000000 32769 gdm 600 393216 2 dest 0x00000000 65538 gdm 600 393216 2 dest 0x00000000 98307 gdm 600 393216 2 dest 0x00000000 163844 oracle 640 12582912 26 0x00000000 196613 oracle 640 536870912 26 0x00000000 229382 oracle 640 524288000 26 0x0f98b25c 262151 oracle 640 2097152 26 0x00000000 294920 gdm 600 393216 2 dest SGA 크기가 1GB 인인스턴스를기동한후 used 는 733 MB, cached 영역이 416 MB 로증가한것을확인할수있다. 이는오라클을기동하여오라클이소유한 shared memory 가 2GB 임에도불구하고처음부터 SGA 전부를메모리에생성하지않는다는것이다. SQL*Plus 에서대량의테이블을 select 하는쿼리를특정세션에서실행해보자. 14:56:21 <SCOTT@DB11G> 1 select count(*) from t; COUNT(*) --------- 19200000 15:01:16 <SCOTT@DB11G> 1 select segment_name, bytes/1024/1024 Part 1 ORACLE 219
15:01:39 2 from dba_segments 15:01:46 3 where segment_name = 'T'; SEGMENT_NAME BYTES/1024/1024 -------------- ----------------- T 440 [oracle@ora11 ~]$ free -m Mem: 2002 1233 769 0 53 898 -/+ buffers/cache: 282 1720 오라클에서세그먼트크기가 440 MB 인테이블을 select 할경우 cached 898 MB 까지증가한 것을확인할수있다. 결과적으로 free 영역도 769 MB 로감소하였다. 이때, 크기가 1GB 인파 일을하나생성해보자. [oracle@ora11 ~]$ cd /u01 [oracle@ora11 u01]$ dd if=/dev/zero of=test bs=1024k count=1000 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 10.5086 s, 99.8 MB/s [oracle@ora11 u01]$ free -m Mem: 2002 1983 19 0 35 1654 -/+ buffers/cache: 292 1709 [oracle@ora11 sc]$ vmstat 1 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 806040 54688 922292 0 0 0 32 912 1455 0 3 97 0 0 0 0 0 806048 54688 922292 0 0 0 0 835 1420 0 2 98 0 0 0 0 0 806048 54688 922292 0 0 0 16 919 1433 0 4 96 0 0 0 2 0 482268 54840 1226700 0 0 152 92712 1422 1531 0 26 69 6 0 0 2 0 431056 54840 1277264 0 0 0 38400 1318 1634 1 15 22 63 0 1 1 0 360252 54840 1345448 0 0 0 75460 1437 1881 0 9 0 91 0 1 2 0 300732 54840 1400220 0 0 0 56140 1617 1832 6 13 0 80 0 0 3 0 245428 54840 1454016 0 0 0 49152 1405 1775 0 11 0 89 0 220 2013 기술백서 White Paper
0 3 0 200912 54844 1499644 0 0 4 48688 1342 1726 0 11 0 89 0 0 2 0 181940 54856 1521548 0 0 8 49172 1129 1573 0 8 2 89 0 1 1 0 79268 54876 1614780 0 0 20 83612 1161 1443 0 12 42 46 0 0 1 0 16268 51732 1680336 0 0 4 55688 1416 1671 0 14 4 82 0 0 1 0 22156 51736 1680344 0 0 4 0 1002 1440 0 2 48 49 0 1 1 0 16972 36584 1692260 0 0 1392 266328 2461 1730 1 43 16 41 0 0 0 0 19824 36584 1693676 0 0 1040 24576 1396 1612 1 8 67 23 0 0 0 0 19832 36584 1693604 0 0 0 0 910 1447 0 3 97 0 0 0 0 0 19832 36584 1693612 0 0 8 32 880 1440 0 3 96 1 0 0 0 0 19956 36584 1693612 0 0 0 0 881 1473 0 2 98 0 0 크기가 1 GB 인파일을생성할경우, free 는 19 MB 로급격히감소하고 used 부분이 1,983 MB 까지증가하였다. 이중 1,654 MB 가 cached 영역에생성되었으며, buffers 영역도일부감소한것을볼수있다. 그렇다면현재메모리전체사이즈보다큰파일을생성할경우메모리변화는어떻게되는지살펴보자. [oracle@ora11 u01]$ dd if=/dev/zero of=test bs=1024k count=4000 4000+0 records in 4000+0 records out 4194304000 bytes (4.2 GB) copied, 9.29048 s, 451 MB/s [oracle@ora11 sc]$ free -m Mem: 2002 1975 27 0 35 1635 -/+ buffers/cache: 303 1698 [oracle@ora11 sc]$ vmstat 1 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 16492 36604 1692316 0 0 959 1217 384 481 1 5 84 10 0 0 0 0 16492 36604 1692316 0 0 0 0 853 1439 0 2 98 0 0 0 0 0 16492 36604 1692316 0 0 0 32 887 1410 0 3 97 0 0 0 0 0 16492 36604 1692316 0 0 0 32 885 1471 0 2 97 0 0 1 0 0 16492 36604 1692316 0 0 0 0 894 1445 0 2 98 0 0 0 0 0 16492 36604 1692316 0 0 0 0 940 1485 0 3 96 0 0 0 0 0 16500 36604 1692316 0 0 0 32 947 1462 0 4 96 0 0 1 0 0 484972 36604 1236120 0 0 12 0 1042 1481 0 7 92 1 0 1 1 0 424444 36604 1288272 0 0 0 393644 2506 1146 0 76 20 3 0 2 0 0 15612 36608 1690140 0 0 0 422540 2469 805 0 88 8 4 0 Part 1 ORACLE 221
2 0 0 16604 36404 1678424 0 0 72 471500 2786 1629 0 73 3 24 0 1 1 0 15612 36424 1683244 0 0 20 328764 3023 2026 0 73 5 22 0 2 3 0 16852 36424 1671024 0 0 0 525444 2687 1473 0 82 8 10 0 3 1 0 16728 36424 1681788 0 0 0 402584 2778 1483 0 75 15 10 0 1 1 0 16852 36344 1681964 0 0 4 403584 2889 1850 0 82 8 10 0 4 0 0 14000 36344 1684544 0 0 0 591664 2876 1213 0 90 4 7 0 4GB 크기의파일을생성하는동안 vmstat 으로메모리변화를살펴보면, free 영역이 16 MB 인상태에서 cached 영역의메모리일부를 free 상태로전환한다는것을알수있다. free 로전환된메모리는파일이생성되는시점에다시 cached 상태가되고 free 및 cached 크기가현재상태로수정됨을알수있다. 즉, free 메모리가부족할경우 cached 영역일부를 free 상태로전환하여사용한다는것이다. 이는앞에서설명했듯이 cached 영역이실제로 free 메모리로사용되고있음을보여준다. 여기서한가지확인할것은 free 메모리가부족함에도 swap 은발생하지않았다는것이다. swap 의 used 는여전히 0 인상태로남아있다. 이어서 4GB 파일을바로삭제하면아래와같이 cached 영역의상당부분의메모리가다시 free 영역으로전환된다. 파일을생성하면서 cached 영역의대부분을차지한데이터들이동시에삭제되므로오라클인스터스만생성된시점으로메모리상태가변경된다. 이때오라클인스턴스도이어서 shutdown 시킬경우아래와같이시스템을처음기동할때의메모리상태로변경된다. [oracle@ora11 u01]$ rm test Mem: 2002 664 1338 0 35 357 -/+ buffers/cache: 271 1731 [oracle@ora11 ~]$ sqlplus / as sysdba SQL*Plus: Release 11.2.0.3.0 Production on Fri Nov 1 09:28:57 2013 Copyright (c) 1982, 2011, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0-64bit Production With the Partitioning, OLAP, Data Mining and Real Application Testing options 222 2013 기술백서 White Paper
SQL> shutdown immediate Database closed. Database dismounted. ORACLE instance shut down. Mem: 2002 347 1655 0 35 119 -/+ buffers/cache: 192 1810 지금까지테스트를위해수행된모든내용을메모리에서제거하였어도 cached 영역에는아직 119 MB 가남아있다. 만약이부분또한 free 로전환하고싶다면어떻게하면될까? 리눅스에서는메모리의 buffers 와 cached 상태의메모리를 free 영역으로임의로변경하기위해 /proc/sys/vm/drop_caches 파일의내용을 0 에서 1, 2, 3 중하나의값으로변경하면된다. [root@ora11 ~]# echo 1 > /proc/sys/vm/drop_caches Mem: 2002 249 1752 0 0 60 -/+ buffers/cache: 189 1813 - pagecache 해제 echo 1 > /proc/sys/vm/drop_caches - dentries, inodes 해제 echo 2 > /proc/sys/vm/drop_caches - pagecache, dentries, inodes 모두해제 echo 3 > /proc/sys/vm/drop_caches 파일의값을 '1' 로변경하였더니 cached 값이대부분 free 영역으로전환되었음을볼수있다. 해당파일을직접수정할수도있지만명령어로도가능하다. Mem: 2002 898 1104 0 26 591 Part 1 ORACLE 223
-/+ buffers/cache: 280 1722 [root@ora11 ~]# sysctl -w vm.drop_caches=3 vm.drop_caches = 3 [root@ora11 ~]# [root@ora11 ~]# [root@ora11 ~]# Mem: 2002 607 1394 0 2 325 -/+ buffers/cache: 280 1722 결론 유닉스계열의 O/S 에서메모리사용률을정확하게모니터링하기란쉽지않다. 그이유는빠른 CPU 성능에 I/O 속도를맞추기위해메모리의상당부분을디스크캐시로사용하기때문이다. 디스크캐시는 I/O 가발생할때마다유동적으로변화하고특정커널파라미터를통해임계값을설정하여그이상으로는증가하지못하게도할수있다. 이러한기능은각벤더마다조금씩차이가있다. 메모리사용률을정확한수치로계산하기란쉽지않으며메모리를확인하는명령어에따라약간의차이가있다. 따라서, 메모리를모니터링할때얼마나가용한메모리가남았는지, 현재메모리가부족하여 SWAP 을지속적으로사용하고있는지등을확인하는것이올바른모니터링방법이라할수있겠다. 참고문헌 http://stackoverflow.com/questions/9724396/understanding-buffers-and-cached-fromfree-command, http://www.slideshare.net/yvelikanov/all-oracle-dbas-have-to-knowabout-unix-memory-monitoring 224 2013 기술백서 White Paper