Messages in this thread Patch in this message | | | Date | Thu, 26 Jun 97 08:20 | From | (Krzysztof Strasburger) | Subject | Page cache and swapping |
| |
Hi all! I have seen many times postings about page cache behavior under linux 2.0.x. Some weeks ago I tried to run linux+Xfree86-2.11+netscape 2.0 on 8 MB machine. It was almost unusable. Over 4 MB of memory was frozen in page cache, the machine swapped like a hell and after moving the mouse I had to wait for the moving of the cursor. I created this small patch, which modifies the memory freeing policy. It is against 2.0.30, but should work with pre-2.0.31 too. After applying it the performance was much better, but the page cache became very small (40-200 KB) while running programs mentioned above. WARNING: It is not to be blindly applied! I'm not sure, if it does not introduce deadlocks in other parts of the kernel, so please share your wisdom with me. Looking at shrink_mmap in mm/filemap.c I found, that shared pages (page->count > 1) are inviolable. Additionally, the referenced bit is set, so next time the page is not freed again, even if it was _not_ used. In other parts of the kernel I found that page->count is increased on purpose to lock the page in memory. On the other hand, page->count is for page cache pages (with no buffers attached to it) the number of processes "seeing" the page. So, I supposed that removing a shared, but unused page from page cache should not be disasterous. The patch allows removing shared pages from page cache and removes setting of the referenced bit for all shared pages. Krzysztof Strasburger
--- linux-orig/mm/filemap.c Wed Sep 11 14:57:19 1996 +++ linux/mm/filemap.c Tue Jun 24 09:25:16 1997 @@ -160,38 +160,41 @@ } while (tmp != bh); } + /* If it has been referenced recently, don't free it */ + if (clear_bit(PG_referenced, &page->flags)) + goto next; + + /* Original note: */ /* We can't throw away shared pages, but we do mark them as referenced. This relies on the fact that no page is currently in both the page cache and the buffer cache; we'd have to modify the following test to allow for that case. */ - switch (page->count) { - case 1: - /* If it has been referenced recently, don't free it */ - if (clear_bit(PG_referenced, &page->flags)) - break; - - /* is it a page cache page? */ - if (page->inode) { - remove_page_from_hash_queue(page); - remove_page_from_inode_queue(page); - __free_page(page); - return 1; - } + /* Why shared pages can't be freed? This modification + (sorry for the programming style) allows freeing shared + page cache pages. Shared buffers are treated as previously, + but they are not marked as referenced. Ah, try_to_free_buffer + is called with priority passed to current function, not 6 + in any case. + KS */ - /* is it a buffer cache page? */ - if (bh && try_to_free_buffer(bh, &bh, 6)) + /* is it a buffer cache page? */ + if (bh) { + if (page->count == 1) { + if (try_to_free_buffer(bh, &bh, priority)) return 1; - break; - - default: - /* more than one users: we can't throw it away */ - set_bit(PG_referenced, &page->flags); - /* fall through */ - case 0: - /* nothing */ + } + goto next; + } + /* is it a page cache page? */ + if (page->inode) { + remove_page_from_hash_queue(page); + remove_page_from_inode_queue(page); + __free_page(page); + return 1; } + next: page++; clock++;
| |