From eee827ad6ffb1eb6ea4684478cfcfbb6f1884cbe Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 10 Jun 2008 05:02:09 +0000 Subject: [PATCH] Change bwillwrite() to smooth out performance under heavy loads. Blocking based on strict hystersis was being used to try to gang flushes together but filesystems can still blow out the buffer cache and cause processes to block for long periods of time waiting for the dirty count to drop significantly. Instead, as the number of dirty buffers exceeds the desired maximum bwillwrite() imposes a dynamic delay which increases as the number of dirty buffers increase. This improves the stall behavior under heavy loads and keeps the system responsive. TODO: The algorithm needs to have a per-LWP heuristic to penalize heavy writers more then light ones. --- sys/kern/vfs_bio.c | 53 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 1c3f0c7658..38c45ff4ab 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -12,7 +12,7 @@ * John S. Dyson. * * $FreeBSD: src/sys/kern/vfs_bio.c,v 1.242.2.20 2003/05/28 18:38:10 alc Exp $ - * $DragonFly: src/sys/kern/vfs_bio.c,v 1.102 2008/05/09 07:24:45 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_bio.c,v 1.103 2008/06/10 05:02:09 dillon Exp $ */ /* @@ -968,19 +968,50 @@ bowrite(struct buf *bp) void bwillwrite(void) { - if (runningbufcount + numdirtybuffers >= hidirtybuffers / 2) { + int mid1 = hidirtybuffers / 2; + int mid2 = mid1 + hidirtybuffers / 4; + int delay; + int count; + int priority = 0; + + count = runningbufcount + numdirtybuffers; + + /* + * Nothing to do if nothing is stressed. + */ + if (count < mid1) + return; + + /* + * Get the buffer daemon heated up + */ + bd_wakeup(1); + + while (count >= mid2) { + /* + * Start slowing down writes, down to 1 per second. + */ + if (count < hidirtybuffers) { + delay = (count - mid2) * hz / (hidirtybuffers - mid2); + delay = delay * 10 / (10 + priority); + if (delay == 0) + delay = 1; + tsleep(&count, 0, "flstik", delay); + return; + } + + /* + * Now we are really in trouble. + */ bd_wakeup(1); - while (runningbufcount + numdirtybuffers >= hidirtybuffers) { - bd_wakeup(1); - spin_lock_wr(&needsbuffer_spin); - if (runningbufcount + numdirtybuffers >= - hidirtybuffers) { - needsbuffer |= VFS_BIO_NEED_DIRTYFLUSH; - msleep(&needsbuffer, &needsbuffer_spin, 0, - "flswai", 0); - } + spin_lock_wr(&needsbuffer_spin); + count = runningbufcount + numdirtybuffers; + if (count >= hidirtybuffers) { + needsbuffer |= VFS_BIO_NEED_DIRTYFLUSH; + msleep(&needsbuffer, &needsbuffer_spin, 0, "flswai", 0); spin_unlock_wr(&needsbuffer_spin); } + count = runningbufcount + numdirtybuffers; } #if 0 /* FUTURE - maybe */ -- 2.11.4.GIT