It is very common that your system is suffered from lack of free memory and found that most of the physical memory was consumed by ‘buffer/cache’.
Because ‘buffer/cache’ can be reclaimed when memory is under pressure, user usually doesn’t need to worry about that and most of the time, keeping cache is desirable as it can improve system performance.
But, sometimes, there’s a case that cache doesn’t have meaning such as backup filesystem or handling lots of files that only use once. In that case, early freeing could be a better choice. To drop caches/buffers, you can use following method.
sync echo 3 > /proc/sys/vm/drop_caches
You can use one of three possible values – 1 : pagecache, 2 : dentries and inodes, 3 : pagecache, dentries and inodes.
But, sometimes, even with above command you can see lots of caches are still in memory. Why it happens?
There are two possible reasons for this.
One is dirty pages that need to be write back to file later.
Second reason is mmaped files. You can see this in following code snippet:
unsigned long __invalidate_mapping_pages(struct address_space *mapping, pgoff_t start, pgoff_t end, bool be_atomic) { struct pagevec pvec; pgoff_t next = start; unsigned long ret = 0; int i; pagevec_init(&pvec, 0); while (next <= end && pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) { for (i = 0; i index of an * unlocked page. But we're not allowed to lock these * pages. So we rely upon nobody altering the ->index * of this (pinned-by-us) page. */ index = page->index; if (index > next) next = index; next++; if (lock_failed) continue; From here >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> if (PageDirty(page) || PageWriteback(page)) goto unlock; if (page_mapped(page)) goto unlock; To here >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ret += invalidate_complete_page(mapping, page); unlock: unlock_page(page); if (next > end) break; } pagevec_release(&pvec); if (likely(!be_atomic)) cond_resched(); } return ret; }
As you can see, dirty pages, write back pages, or mapped pages are not reclaimable. To show how mapped pages are handled, I created a simple code.
#include #include #include #include #include #include #include #include int main(int argc, char **argv) { int fd = -1; unsigned long size = 4096, status, i, sum; char *area; pid_t pid; fd = open("test.img", O_RDONLY); size = llseek(fd, 0, SEEK_END); llseek(fd, 0, SEEK_SET); printf("size = %un", size); area = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, fd, 0); printf("area = %pn", area); sum = 0; for (i = 0; i /proc/sys/vm/drop_caches"); sleep(5); printf("nnAfter ran 'echo 3 > /proc/sys/vm/drop_caches'n"); system("free"); munmap(area, size); sleep(1); printf("nnAfter unmap the filen"); system("free"); exit(0); }
To test this, you just need to run following steps:
[root@localhost Work]# dd if=/dev/zero of=test.img bs=1M count=1024 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 2.75285 s, 390 MB/s [root@localhost Work]# sync; echo 3 > /proc/sys/vm/drop_caches [root@localhost Work]# free total used free shared buffers cached Mem: 1022992 207796 815196 0 196 20792 -/+ buffers/cache: 186808 836184 Swap: 2031612 240040 1791572 [root@localhost Work]# ./mmap_test size = 1073741824 area = 0x7fd6cb45a000 Reading Done total used free shared buffers cached Mem: 1022992 431024 591968 0 332 274040 -/+ buffers/cache: 156652 866340 Swap: 2031612 271140 1760472 After ran 'echo 3 > /proc/sys/vm/drop_caches' total used free shared buffers cached Mem: 1022992 431016 591976 0 332 273344 -/+ buffers/cache: 157340 865652 Swap: 2031612 271000 1760612 After unmap the file total used free shared buffers cached Mem: 1022992 174780 848212 0 408 20760 -/+ buffers/cache: 153612 869380 Swap: 2031612 270960 1760652 [root@localhost Work]#
See, caches are only dropped when mapped pages are freed.
Leave a Reply