From owner-freebsd-bugs Sat Jun 24 04:43:23 1995 Return-Path: bugs-owner Received: (from majordom@localhost) by freefall.cdrom.com (8.6.10/8.6.6) id EAA05980 for bugs-outgoing; Sat, 24 Jun 1995 04:43:23 -0700 Received: from blob.best.net (blob.best.net [204.156.128.88]) by freefall.cdrom.com (8.6.10/8.6.6) with ESMTP id EAA05972 for ; Sat, 24 Jun 1995 04:43:20 -0700 Received: from shell1.best.com (shell1.best.com [204.156.128.10]) by blob.best.net (8.6.12/8.6.5) with ESMTP id EAA29260 for ; Sat, 24 Jun 1995 04:42:18 -0700 Received: (dillon@localhost) by shell1.best.com (8.6.12/8.6.5) id EAA11425; Sat, 24 Jun 1995 04:41:58 -0700 Date: Sat, 24 Jun 1995 04:41:58 -0700 From: Matt Dillon Message-Id: <199506241141.EAA11425@shell1.best.com> To: bugs@freebsd.org Cc: rdy@best.com Subject: non-fatal bug in vm/vm_pageout.c Sender: bugs-owner@freebsd.org Precedence: bulk I think I've found an algorithmic bug in the pager code. in vm/vm_pageout.c, in vm_pageout_scan(), a page is moved to the end of the active queue if: * if its busy or held * if it has been referenced * act_count is greater the zero. The problem is that in the case where the page has been referenced, the reference flag is *cleared* and the page is then moved to the end of the queue. Noe, if the scan happens to reach the end of the queue, it will hit that page AGAIN, the reference count will be cleared, so it will decrement the act_count and move the page to the end of the queue AGAIN... in otherwords, it will repeatedly access the last N pages hundreds of times in that one loop, blowing their act_count and then deciding to page them out, EVEN THOUGH THEY MAY BE HEAVILY REFERENCED! The result is that act_count is effectively defeated. vm_pageout_object_deactivate_pages() would also have this problem but since it limits its scan to object->resident_page_count I think it's safe. My suggestion: When act_count is decremented, leave the page where it is... don't move it to the end of the queue. That is, around line 717 of vm/vm_pageout.c, remove the TAILQ_REMOVE/TAILQ_INSERT calls in the else. This way, all page's act_count's get equal treatment, and if the page happens to get referenced again it will be moved to the end of the queue anyway. Secondary problem: act_count only declines when paging is required. This virtually guarentees that no pages will necessarily be pagable in the first loop, before it resorts to vm_daemon(). What really needs to happen is for the active queue to be scanned say once every few seconds and act_count decremented or incremented according to whether the page has been referenced or not. Thus, when paging finally becomes necessary, act_count already has a basis. My suggestion: wakeup the pagedaemon once every 5 seconds and have it do a full scan checking for referenced/unreferenced pages, incrementing or decrementing act_count as appropriate. It would move pages to the end of the queue if it finds them referenced (as per normal), and it would move pages to the front of the queue if act_count reaches 0 (never minding the fact that newer pages more recently dropping to 0 will be paged out before older pages that have dropped to 0). -Matt Matthew Dillon VP Engineering, BEST Internet Communications, Inc. , [always include a portion of the original email in any response!]