Bug 84903

Summary: Incorrect initialization of nswbuf
Product: Base System Reporter: Ade Lovett <ade>
Component: kernAssignee: Ade Lovett <ade>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: Unspecified   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description Ade Lovett freebsd_committer freebsd_triage 2005-08-14 10:10:11 UTC
Whilst attempting to nail down some serious performance issues (compared
with 4.x) in preparation for a 6.x rollout here, we've come across
something of a fundamental bug.

In this particular environment (a Usenet transit server, so very high
network and disk I/O) we observed that processes were spending a
considerable amount of time in state 'wswbuf', traced back to getpbuf()
in vm/vm_pager.c

To cut a long story short, the order in which nswbuf is being
initialized is completely, totally, and utterly wrong -- this was
introduced by revision 1.132 of vm/vnode_pager.c just over 4 years ago.

In vnode_pager.c we find:

static void
vnode_pager_init(void)
{
	vnode_pbuf_freecnt = nswbuf / 2 + 1;
}

Unfortunately, nswbuf hasn't been assigned to yet, just happens to be
zero (in all cases), and thus the kernel believes that there is only
ever *one* swap buffer available.

kern_vfs_bio_buffer_alloc() in kern/vfs_bio.c which actually does the
calculation and assignment, is called rather further on in the process,
by which time the damage has been done.

The net result is that *any* calls involving getpbuf() will be
unconditionally serialized, completely destroying any kind of
concurrency (and performance).

Given the memory footprint of our machines, we've hacked in a simple:

	nswbuf = 0x100;

into vnode_pager_init(), since the calculation ends up giving us the
maximum number anyway.  There are a number of possible 'correct' fixes
in terms of re-ordering the startup sequence.

With the aforementioned hack, we're now seeing considerably better
machine operation, certainly as good as similar 4.10-STABLE boxes.

As per $SUBJECT, this affects all of RELENG_5, RELENG_6, and HEAD, and
should, IMO, be considered an absolutely required fix for 6.0-RELEASE.

Fix: We have implemented a local hack as above, given that the
	memory footprint of the machines would result in the
	maximal value of nswbuf being assigned in any case.

	This is not a real fix however.

	A solution has been offered by Alexander Kabaev <kabaev@gmail.com>
	as follows, which appears to do the right thing, at least on
	RELENG_6/i386, which is the only type of machine I have easy
	access to for testing purposes.

	In my opinion, it would be a fatal error to release 6.0 in
	any shape or form without addressing this issue.
How-To-Repeat: 
	N/A
Comment 1 Ade Lovett freebsd_committer freebsd_triage 2005-08-16 19:55:22 UTC
State Changed
From-To: open->closed

Fixed in revision 1.223 of sys/vm/vnode_pager.c et al. 
Subsequently MFC'd to RELENG_6 (1.221.2.2) and RELENG_5 (1.196.2.8) 


Comment 2 Ade Lovett freebsd_committer freebsd_triage 2005-08-16 19:55:22 UTC
Responsible Changed
From-To: freebsd-bugs->ade

Fixed in revision 1.223 of sys/vm/vnode_pager.c et al. 
Subsequently MFC'd to RELENG_6 (1.221.2.2) and RELENG_5 (1.196.2.8)