Thread: memory not released after running program

  1. #16
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    That won't work if you are using a 32 bit OS that has more than 3GB of RAM

    At any rate, I think this is the command to flush the system cache:
    Code:
    echo 3 > /proc/sys/vm/drop_caches

  2. #17
    {Jaxom,Imriel,Liam}'s Dad Kennedy's Avatar
    Join Date
    Aug 2006
    Location
    Alabama
    Posts
    1,065
    bithub: That does NOT clear the FS cache from the kernel memory. What happens is the memory is marked as "freed" but the kernel does not actually drop those pages until (1) a write of the file occurs -- In this case you only have a new copy of the same file in memory, the original read() file is dropped or (2) if you umount the file system. If you don't believe me, look around in the code. I found this problem about two years ago. . . I asked the maintainers of the code why and they said "because." <-- This is not a joke.

    As far as eating memory goes, that doesn't work either. The problem I was having was that tar couldn't get enough memory since the KERNEL had that memory for cache. Kernel memory overrides user memory, thus tar would not function properly.

    The Linux Kernel maintainers say that in "normal operating conditions" the kernel will release the cache after a period of time. My problem was that I was chewing all 64MB of my memory by off-loading ~2GB of data to a 4GB jump drive so that I could reconfigure my CF device (on-the-fly without user intervention). After the initial read of the data I had to unmount and remount to get the sucker to behave properly. Likewise, after the write I had to unmount again. I tried _EVERYTHING_ to get it to do it any other way, but the only success I had was to umount the filesystems (both the CF and the USB memory stick). (BTW, the original filesystem on the CF was ext3 mounted with noatime -- This would hang at boot sometimes, which in an embedded system is terrible, so we changed it to Reiserfs to fix the problem.)

  3. #18
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    bithub: That does NOT clear the FS cache from the kernel memory.
    So you're saying that even though every memory diagnostic utility will show that the memory has moved from "cached" to "free", the memory has not actually been released from the cache? I disagree with this. Now the above command will not free "dirty" cache pages. To get around this you can tell the kernel to write out dirty cache pages to disk using the "sync" command. Also, if the drop_caches proc didn't work, I would have expected Andrew Morton to say as much in this bug.

    The problem I was having was that tar couldn't get enough memory since the KERNEL had that memory for cache. Kernel memory overrides user memory, thus tar would not function properly.
    The kernel should release cached memory to the application if the application attempts to allocate more memory than what is "free" on the system. I don't see how the system cache can "override" user memory, that's not how the Linux kernel works (Unless I have been misinformed all these years, which is possible).

    My problem was that I was chewing all 64MB of my memory by off-loading ~2GB of data to a 4GB jump drive so that I could reconfigure my CF device (on-the-fly without user intervention). After the initial read of the data I had to unmount and remount to get the sucker to behave properly.
    You could have written the 2GB using O_DIRECT. This would bypass the system cache entirely. Of course I'm not convinced that the cache was the root of your problem (see my above comment regarding the kernel freeing cache memory when an application requests more). Then again, I've been wrong before, so take this with a grain of salt

  4. #19
    {Jaxom,Imriel,Liam}'s Dad Kennedy's Avatar
    Join Date
    Aug 2006
    Location
    Alabama
    Posts
    1,065
    Quote Originally Posted by Linus Torvalds
    The right way to do it is to just not use O_DIRECT.

    The whole notion of "direct IO" is totally braindamaged. Just say no.

    This is your brain: O
    This is your brain on O_DIRECT: .

    Any questions?

    I should have fought back harder. There really is no valid reason for EVER
    using O_DIRECT. You need a buffer whatever IO you do, and it might as well
    be the page cache. There are better ways to control the page cache than
    play games and think that a page cache isn't necessary.

    So don't use O_DIRECT. Use things like madvise() and posix_fadvise()
    instead.

    Linus
    Quote Originally Posted by bithub
    So you're saying that even though every memory diagnostic utility will show that the memory has moved from "cached" to "free", the memory has not actually been released from the cache? I disagree with this. Now the above command will not free "dirty" cache pages. To get around this you can tell the kernel to write out dirty cache pages to disk using the "sync" command. Also, if the drop_caches proc didn't work, I would have expected Andrew Morton to say as much in this bug.
    Through 2.6.18 (at a minimum) Yes. Check out the LKML about it. I cannot remember if that is where I made my stink (Don't have those e-mails anymore -- another job). . . But writing 3 to drop_caches didn't work -- PERIOD. So, if you want to you can disagree -- you're still wrong.

  5. #20
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    The fact that Linus doesn't like O_DIRECT has nothing to do with whether it works or not. I agree with him 100% that you should never need to bypass the page cache. You were the one that was stating that the page cache was limiting your application memory, not me... remember?

    So, if you want to you can disagree -- you're still wrong.
    I did a search on the LKML, and there are a ton of messages about drop_caches. None of those messages say anything about drop_caches not actually dropping cached pages. Can you point us to a single resource at all which backs up your assertion that drop_caches doesn't work? I'm not saying you're wrong, I just find it suspicious that there's no posts that I can find to back up your claims.

    Anyways, since you seem to be so sure of yourself, I did a little checking. Setting the drop_caches proc will execute the following code:

    fs/drop_caches.c
    Code:
    28void drop_pagecache(void)
      29{
      30        struct super_block *sb;
      31
      32        spin_lock(&sb_lock);
      33restart:
      34        list_for_each_entry(sb, &super_blocks, s_list) {
      35                sb->s_count++;
      36                spin_unlock(&sb_lock);
      37                down_read(&sb->s_umount);
      38                if (sb->s_root)
      39                        drop_pagecache_sb(sb);
      40                up_read(&sb->s_umount);
      41                spin_lock(&sb_lock);
      42                if (__put_super_and_need_restart(sb))
      43                        goto restart;
      44        }
      45        spin_unlock(&sb_lock);
      46}
    Which calls the following:
    /fs/drop_caches.c
    Code:
      15static void drop_pagecache_sb(struct super_block *sb)
      16{
      17        struct inode *inode;
      18
      19        spin_lock(&inode_lock);
      20        list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
      21                if (inode->i_state & (I_FREEING|I_WILL_FREE))
      22                        continue;
      23                invalidate_inode_pages(inode->i_mapping);
      24        }
      25        spin_unlock(&inode_lock);
      26}
    Now invalidate_inode_pages() just calls invalidate_mapping_pages():
    /mm/truncate.c
    Code:
     223unsigned long invalidate_mapping_pages(struct address_space *mapping,
     224                                pgoff_t start, pgoff_t end)
     225{
     226        struct pagevec pvec;
     227        pgoff_t next = start;
     228        unsigned long ret = 0;
     229        int i;
     230
     231        pagevec_init(&pvec, 0);
     232        while (next <= end &&
     233                        pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
     234                for (i = 0; i < pagevec_count(&pvec); i++) {
     235                        struct page *page = pvec.pages[i];
     236                        pgoff_t index;
     237                        int lock_failed;
     238
     239                        lock_failed = TestSetPageLocked(page);
     240
     241                        /*
     242                         * We really shouldn't be looking at the ->index of an
     243                         * unlocked page.  But we're not allowed to lock these
     244                         * pages.  So we rely upon nobody altering the ->index
     245                         * of this (pinned-by-us) page.
     246                         */
     247                        index = page->index;
     248                        if (index > next)
     249                                next = index;
     250                        next++;
     251                        if (lock_failed)
     252                                continue;
     253
     254                        if (PageDirty(page) || PageWriteback(page))
     255                                goto unlock;
     256                        if (page_mapped(page))
     257                                goto unlock;
     258                        ret += invalidate_complete_page(mapping, page);
     259unlock:
     260                        unlock_page(page);
     261                        if (next > end)
     262                                break;
     263                }
     264                pagevec_release(&pvec);
     265        }
     266        return ret;
     267}
    As you can see it will skip dirty pages and memory mapped pages. Well invalidate_complete_page() looks like:
    /mm/truncate.c
    Code:
      61static int
      62invalidate_complete_page(struct address_space *mapping, struct page *page)
      63{
      64        if (page->mapping != mapping)
      65                return 0;
      66
      67        if (PagePrivate(page) && !try_to_release_page(page, 0))
      68                return 0;
      69
      70        write_lock_irq(&mapping->tree_lock);
      71        if (PageDirty(page))
      72                goto failed;
      73        if (page_count(page) != 2)      /* caller's ref + pagecache ref */
      74                goto failed;
      75
      76        BUG_ON(PagePrivate(page));
      77        __remove_from_page_cache(page);
      78        write_unlock_irq(&mapping->tree_lock);
      79        ClearPageUptodate(page);
      80        page_cache_release(page);       /* pagecache ref */
      81        return 1;
      82failed:
      83        write_unlock_irq(&mapping->tree_lock);
      84        return 0;
      85}
    Hmm... the function __remove_from_page_cache() sounds like it may actually do something...
    /mm/filemap.c
    Code:
     110/*
     111 * Remove a page from the page cache and free it. Caller has to make
     112 * sure the page is locked and that nobody else uses it - or that usage
     113 * is safe.  The caller must hold a write_lock on the mapping's tree_lock.
     114 */
     115void __remove_from_page_cache(struct page *page)
     116{
     117        struct address_space *mapping = page->mapping;
     118
     119        radix_tree_delete(&mapping->page_tree, page->index);
     120        page->mapping = NULL;
     121        mapping->nrpages--;
     122        __dec_zone_page_state(page, NR_FILE_PAGES);
     123}
    Are you still sure that I'm wrong? By the way, all this code is from 2.6.18 which is the version you claim has the broken drop_caches implementation.

  6. #21
    {Jaxom,Imriel,Liam}'s Dad Kennedy's Avatar
    Join Date
    Aug 2006
    Location
    Alabama
    Posts
    1,065
    Quote Originally Posted by bithub
    Are you still sure that I'm wrong? By the way, all this code is from 2.6.18 which is the version you claim has the broken drop_caches implementation.
    Yes.

  7. #22
    Registered User
    Join Date
    Dec 2010
    Posts
    1

    My problem System not releasing memory and Drop_cache file not their in LInux4.0

    Quote Originally Posted by Kennedy View Post
    Through 2.6.18 (at a minimum) Yes. Check out the LKML about it. I cannot remember if that is where I made my stink (Don't have those e-mails anymore -- another job). . . But writing 3 to drop_caches didn't work -- PERIOD. So, if you want to you can disagree -- you're still wrong.
    When i am using (sync; echo 3 > /proc/sys/vm/drop_caches) its working fine in Linux 5.0 onwards. But in 4.0 A.S version Drop_caches folder is not their . I am facing problem that system is not relesing memory.Please help me How to clear unwanted cache in Linux4.0 versions.

    AVL

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Client-server system with input from separate program
    By robot-ic in forum Networking/Device Communication
    Replies: 3
    Last Post: 01-16-2009, 03:30 PM
  2. Replies: 4
    Last Post: 03-29-2004, 07:56 PM
  3. my C++ program hangs during memory deallocation.
    By the-tzar in forum C++ Programming
    Replies: 6
    Last Post: 03-06-2004, 10:39 AM
  4. Pointer's
    By xlordt in forum C Programming
    Replies: 13
    Last Post: 10-14-2003, 02:15 PM