Cover V05, I01


Kernel Tuning for System I/O under SCO UNIX

Ernest H. Rice III

Proper kernel configuration can make a significant difference in system operation. Kernel parameters can, generally, be divided into two areas: capacity and performance. This article will focus on the proper kernel tuning for system I/O for SCO UNIX systems.

Examples of parameters which govern capacity include:

  • The maximum number of mount points (NMOUNT)

  • The maximum number of open files (NFILE)

  • The maximum number of processes, system-wide (NPROC)

    Examples of parameters which govern performance include:

  • The number of system buffers (NBUF)

  • The number of hash buffers (NHBUF)

    There may appear to be little difference between the two sets of examples, since both quantify some aspect of the kernel. Also, the two types of parameters are not necessarily mutually exclusive. For example, while NFILE does quantify the capacity for open files, a truly excessive value could indirectly impact system performance by usurping memory (perhaps causing a system to swap). In normal use, this would not be the case, but it does illustrate the importance of understanding the underlying effects of each individual parameter.

    NMOUNT, which specifies the maximum number of filesystems (or mount points) has no real impact on the performance of the system. It simply tells the kernel how much space should be reserved, internally, for the mount table. A value that is too small will not impact overall system performance, it will simply limit the number of filesystems to be mounted. Specifying an excessive value for NMOUNT will only waste memory, by causing the kernel to reserve space in its mount table which will never be used. Again, neither the high nor the low setting will impact overall performance (except in the case of a truly excessive value, as discussed above).

    NBUF, on the other hand, indicates how many buffers need to be allocated by the kernel, a quantification, to be sure, one that has several ramifications.

    If too few buffers are allocated, the system will be forced to perform more physical I/O. If the proper number of system buffers is allocated, the system has a better chance of satisfying I/O requests from within the buffer pool (or cache). Since physical I/O is one of the most time-intensive operations performed by the kernel, minimizing physical I/O can have a direct impact on the overall system performance.

    It's thus important to understand the difference between kernel parameters which simply quantify some aspect of the system, and those which directly impact the performance of the system. Moreover, many kernel parameters have a direct relationship to other parameters, so that changing one parameter requires the adjusting of another parameter, often in some sort of relationship to the first parameter. Also, some parameters limit the effects of others. In this case, if the limiting parameter is not changed and the dependent one is, no effect will be realized at all.

    This article will discuss the interrelationships of three kernel parameters used in the optimization of disk I/O. Following the guidelines presented in this article will help you minimize physical disk I/O and increase overall system performance.

    Understanding I/O

    Reading or writing of data to any type of media is one of the most time consuming of computer operations, because it requires the interaction of mechanical equipment. The tape must spin, the disk heads must move, etc. If you can minimize the number of physical reads and writes to media, you can free up the processor to perform other tasks, such as executing instructions, and create the potential for increased system performance.

    Operating systems were designed to take this into account. A buffer pool is allocated to hold data read from, or written to, mass storage devices. If a record read into the buffer pool is needed again before the buffer pool is cleared, no further physical I/O is required; the record is simply retrieved from the pool. As the buffer pool resides in memory and can be reached without a mechanical operation, the data can be retrieved much faster than if a physical I/O had been required.

    A hashing algorithm further improves the performance of the buffer pool by reducing the amount of time required to search for a particular record within the pool. Once again, proper allocation of hashing buffers is critical to optimized performance of the hashing algorithm. Since the hashing algorithm has a direct impact on the time required to retrieve a record from the buffer pool, ensuring appropriate allocation of hashing buffers has a direct impact on optimizing I/O.

    Bringing It All Together

    When SCO UNIX boots, several kernel parameters are automatically configured based on the amount of system resources available at initialization time. One of these is the number of physical buffers used for satisfying I/O requests. This kernel parameter, NBUF, is gated by another kernel parameter, MAXBUF. Regardless of what the kernel believes is the optimal allocation for system buffers, it will never exceed the value specified for MAXBUF. By default, MAXBUF is set to 600, a value which often restricts the optimal allocation of system buffers.

    The first step in optimizing the kernel parameters for physical I/O is to increase the value for MAXBUF to a level which will not thwart the determination of an optimal value for NBUF. To do this, invoke sysadmsh, go to the System->Configure->Kernel->Parameters menu, and select option 1, Disks and Buffers. Cycle through the parameters, and when MAXBUF appears, reset it to a large value, say 8192 (8K) to start with. Once you have reset this value, rebuild the kernel, using the sysadmsh menu option of System->Configure->Kernel->Rebuild. Rebuild, then reboot the system.

    While the system is rebooting, look at the messages displayed on the screen. At or near the bottom, a message will appear saying something like:

    i/o bufs: XXXX k

    This indicates the number of system buffers the kernel determined was optimal at boot time. If this value is less than 8192K, you can proceed to the next step, otherwise go back to the System->Configure->Kernel->Parameters menu of sysadmsh, and increase the value of MAXBUF again, this time setting it to 16384 (16K). Rebuild the kernel again, and reboot. Continue this procedure, increasing MAXBUF each time, until the message displayed at boot time indicates that a value less than the value of MAXBUF is being used for i/o bufs.

    Having determined the optimal value for NBUF, you need next to adjust the value used to determine how many hash buffers are to be allocated. Note that you need not adjust NBUF by hand, as it is determined automatically at boot time by the kernel.

    To determine the optimal value for NHBUF, divide the value displayed at boot time for the number of i/o bufs by four. Take the result and round it up to the next power of two. The resulting value is what you should specify for NHBUF. On my system, with 16Mb of memory, the optimal value for i/o bufs (as determined by the kernel at boot time), is 1500K. I divided this value by four and got 375. I rounded this value to the next higher value of two, and got a value for NHBUF of 512.

    Once the value for NHBUF has been determined, run sysadmsh again. Return to the System->Configure->Kernel->Parameters menu, select option 1 (Disks and Buffers), and set the new value for NHBUF. Go to the System->Configure->Kernel->Rebuild menu of sysadmsh and rebuild the kernel.

    There is still a little bit of work to do. In the first step the value of MAXBUF was inflated to allow the kernel to determine the optimal value of NBUF. Once this value was determined, the value of NHBUF was set according to the value of NBUF, but MAXBUF is still at the inflated value. You could leave it alone, but if you do, and you add memory someday, the kernel will dutifully determine a new value for NBUF at boot time, and the value for NHBUF which was based on the old value for NBUF will no longer be appropriate. This being the case, it is a good idea to reset the value for MAXBUF to the value the kernel displayed for i/o bufs at boot time. In the example I discussed earlier, where my machine displayed a value of 1500, Iwould specify a value of 1500 for MAXBUF.

    Once again, return to sysadmsh, go to the Configure->System->Kernel->Parameters menu, and select Disks and Buffers. Reset MAXBUF as discussed, and then rebuild the kernel via the System->Configure->Kernel->Rebuild menu option. Reboot the system, and double-check that the value displayed at boot time for i/o bufs is still the value shown earlier. If it is the same value, your disk I/O should now be optimized.

    Monitoring Buffer Usage

    Once the kernel is optimized, you may want to monitor the usage of the buffer pool. Ideally, this will show you how effective the buffer pool is in reducing costly physical I/O.

    Monitoring of most system activity is performed via the sar(1) command. sar(1) has many different options, and these can be very confusing. For our purposes, the -b option is appropriate. To test this, enter:

    sar -b

    This will show you several columns of output. The two columns of greatest value for present purposes are those labeled %rcache and %wcache. These represent the percentages of read and write requests, respectively, which have been satisfied from the cache (or buffer pool). The %rcache value should be greater than the %wcache value, and values should be in the 90-95% range for %rcache, and in the 80-90% range for %wcache. If the %rcache value falls below 90% or the %wcache value falls below 70%, you should revisit the kernel parameters for buffer allocation.

    If you run sar(1) soon after the system boots, its output may be of little value. It is better to run it after the system has been up and running for a bit, so that sar(1) has more data at its disposal, and thus can offer a more accurate representation of buffer pool usage.

    In addition, when the system is "live," sar(1) lets you take snapshots of various aspects of system usage, at periodic intervals. You could, for example, see the buffer pool hit ratios every so many seconds, for a specified number of intervals. For example, the command:

    sar -b 10 20

    would run sar(1) every 10 seconds, displaying buffer information each time. The command would be repeated 20 times and the information displayed would be indicative of buffer usage during the specified interval.

    Faster Floppy Diskettes

    We all have to write to, or read from, floppy diskettes from time to time. If you are like me, you've often wished these procedures could run a little faster. Here is a simple tip that can reduce your floppy diskette transfer time.

    When you format a floppy diskette, specify an interleave of two. The default interleave is one, and although compatible with MS-DOS, the value of one is less than optimal. Try it. If you are using a 3.5-inch high density diskette, enter:

    format -i2 /dev/rdsk/f03ht

    The resulting diskette should have better performance than one formatted without the -i2 option. Everything comes with a price; however. The diskettes formatted with an interleave of two will most likely have to be reformatted with an interleave of one if they are ever to be read on an MS-DOS system.

    Although most diskette drives should be able to read from or write to diskettes formatted on another system using an interleave of two, if you plan to use these diskettes on multiple machines, test one first, as some machines may have problems reading or writing to them.

    Back It Up!

    Finally, since you have reconfigured the kernel, I strongly recommend that you create a new set of Emergency Boot and Root diskettes. You can do this via the mkdev fd command; the procedure requires two 3.5-inch High-Density diskettes.


    This article has covered the tuning and monitoring of three kernel parameters that can have a dramatic impact on disk I/O efficiency. Other kernel parameters also come into play in the optimization of Disk I/O. These parameters are more specialized, often geared to a specific filesystem type, and, in many cases, will not have as dramatic an impact as NBUF, NHBUF, and MAXBUF. However, should you wish to investigate these possibilities, take a look at the following parameters:






    About the Author

    Ernest Rice III is president of ehr3 & Associates, Inc., a New Jersey-based consulting firm and UNIX development house. In 1983 he joined Bell Laboratories as a Member of Technical staff in UNIX Development, where he was responsible for curses(3X) and terminfo(4) for SVR2.1 through SVR4, was an original member of the OPENLOOK development team, and lead pioneering efforts in the Exploratory Language Development Group. His firm provides consulting services for New York borkerage houses, and produces a complete line of UNIX software products for system administrators, developers, and end-users. He can be reached via e-mail at