Optimising FreeBSD and it's kernel:
A simple step by step guide, by Avleen Vig
This is a very simple step by step guide on optimising your FreeBSD server or workstation.
It doesn't go into a great amount of detail, but after spending several months searching for
one source of simple optimisation information and failing, I wrote this paper. All the
suggestions listed here are known optimisations available to you if you know where to find
them and have the time to do so. There is nothing secret, or special or amazing in this paper,
just information on how you can optimise your system.
It can mostly be applied to the other BSDs too, but not Linux. There are plenty of Linux documents out there, so go find one of those. I'm sure there are several HOWTO's. This document is true as of the release of FreeBSD 4.8. Some parts of it, such as optimising your kernel, can also be applied to some previous releases.
Before we proceed any further you should know that as with any system tuning, we have to
accept the possibility that something will break. If you're going to recompile the kernel,
please read the following URL first. If possible print a copy of the page and keep it with
you. It'll help you if your new kernel doesn't boot:
First we need to make sure we have the right source files downloaded. The best place to start, is the original source files that were intended for the release of FreeBSD you are using. We assume you have a fairly recent release - not more than 2 revisions (approx 6 to 8 months) old. Execute the following command and follow the steps to get the sources needed to recompile a kernel:
Congratulations, you now have a know working kernel source tree installed in
cd /usr/src/sys/i386/conf and follow the next steps.
You should see two files in this directory, GENERIC and LINT. These are both kernel
configuration files and contain all the data the kernel needs from the user, to compile. They
are very easy to read and edit.
GENERIC is the Generic kernel configuration which should work with every system. LINT contains a list of all possible kernel configuration file directives. We won't worry about LINT just yet. First lets trim the GENERIC kernel down and get comfortable with that. Follow these steps to success:
viand have written a cheat sheet for new
'GENERIC'in the line
'ident GENERIC'is the name of your kernel. This can be any single alphanumeric word with no spaces or punctuation. I recommend you keep it short. Again, it is traditional to name this to be the same as your machine hostname and kernel configuration file name but it is not required. It is informational only.
maxusersline does not actually limit the maximum number of users. It is used internally with an algorithm in the param.c file to determine the sizes and numbers of certain tables. This can remain at the default. As of FreeBSD 4.7 this is set to '0' by default, which causes the actual value to be auto-sized depending on the amount of memory that you have.
'[KEEP THIS!]'should not be removed. FreeBSD needs these things! Anything labelled
'(required!)'should also be kept if you're going to use that type of device. For example, if you're going to use SCSI devices, don't comment out
'scbus'. If you're not using any SCSI devices, then you should comment this out. Some PCI network cards require the inclusion of
'device miibus'. These are noted in your kernel configuration file. If you don't use these NICs you can also comment this out.
config <filename>, where <filename> is your configuration file. This only takes a moment and it will tell you which directory is your compile directory. That is where we will compile the kernel. The config command creates the directory structure and files which the next steps use in compiling the kernel.
cdto the directory that
configgave and issue these commands in turn, each after the previous has finished:
# make depend
# make install
That is it. Really! If something breaks and your new kernel will not boot, DON'T PANIC! Read the 'Kernel Does Not Boot' section of the URL at the top of the page.
This section is for the slightly more advanced compilation of code and kernels. We will
also briefly mention how to compile a kernel with the debugging symbols built in. The
debugging kernel can be useful when your server or workstation is kernel panicing frequently
and you want to find out why. There is a great article from OnLamp.com on how to debug a
kernel, available at:
First lets look at optimising the compilation of C code itself. One of the key tasks when doing this is to start with as simple a configuration as possible. Hopefully if you've read everything above you'll be at this stage already :-)
You should set a few specific options in /etc/make.conf that will optimise the compilation
of new code on your machine. This means all code will be compiled with these options. If you
set the right ones, they can significantly improve the speed and efficiency with which code is
compiled and executed. They will also help to reduce memory consumption. If you have installed
portupgrade package from
should execute this command after setting these options and updating your ports collection. It
will cause every port you have installed, to have it's latest version downloaded and
recompiled with the optimisations. I think it is worth it:
Updating your ports collection en masse can have other consequences which are worth realising. If the current installed version of your port has undergone a major update (eg exim3 to exim4), a straight upgrade in this way could break your configuration. Use with care! The compilation process can take a while, depending on the speed of your CPU, the amount of memory you have, your internet connection and so on, so if you're on a slow link and wish to download the distfiles for each package first and do the updating offline, you can issue this command to download the distfiles for each port first:
So without further ado, the list of optimisations follows. Initially you won't have an
/etc/make.conf, you can just start editing a file with that name (if you want to
see every possible option to put in the file, reference
CPUTYPE=cpu_type where cpu_type is one of i386, i486, i586, i586/mmx i686, p2, p3, p4, k6, k6-2, or k7. gcc v2, which comes with FreeBSD doesn't yet support the latest Athlon optimisations, so if you have a Thunderbird or other such CPU, just set k7 for now. gcc v3 has better support and this will be available in FreeBSD 5 when it is released toward the end of 2002. NOTE: An important point to remember: Most CPU's of the same family are backward compatible. That is, the K7 is backward compatible with K6 code. Also, Intel-CPU code is mostly universally compatible across CPU families. However, if you compile code for a non-Intel family CPU type and later upgrade to a newer Intel CPU, there is a good chance you may encounter problems unless you recompile your code.
CFLAGS= -O3 -pipe -funroll-loops -ffast-math -O3 sets optimisation level 3 where the largest number of practical optimisations can be made to your code (everything except the kernel). It also does sacrifice binary size for speed. -pipe causes code to be passed between processes using pipes during compilation rather than using temporary files, which has obvious I/O advantages. -funroll-loops causes iterating loops with a known number of iterations to be unrolled into faster executions. -ffast-math breaks IEEE/ANSI strict math rules. One way it does this is by assuming that the square root of numbers are non-negative. This shouldn't be used if you're compiling code that relies on the exact implementation of IEEE or ANSI rules for math functions. Unless you're writing your own code that does just this you shouldn't have a problem with setting this. It should help reduce your compile times.
COPTFLAGS= -O2 -pipe -funroll-loops -ffast-math This is the same as the "CFLAGS" statement, except it's used on the kernel when you compile it. We choose -O2 instead of -O3, because -O3 is known to produce broken kernels. Officially, only -O is supported, but I have never had a problem with -O2. It should be noted at this point that one difference between -O2 and -O3 is that -O3 produces slightly larger code during its optimising. In normal situations this is OK, but we want to compact the kernel down it is another reason to stick with -O2. This also has the same effect as adding the
'makeoptions COPTFLAGS'lines to the kernel config as discussed below.
In you kernel configuration, add the following line after the 'machine' (i386, i486, etc) types near the top:
makeoptions COPTFLAGS="-O2 -pipe -funroll-loops -ffast-math"
This does two things. First the -O2 switch tells the compiler to optimise the compilation. This takes advantage of internal compiler tricks to do this. You could use -O3 to implement even more optimisation tricks, but these aren't supported and -O3 is known to cause many stability issues. -O2 may or may not work for you depending on how many things you have compiled into the kernel and how non-standard your hardware is.
TOP_TABLE_SIZE=number where number is a prime number, at least twice the number of lines in
/etc/passwd. This statement sets the size of the hash that the
top(1)uses for usernames when it runs.
should be set if you have an AMD K5/K6/K6-2 or Cyrix 6x86 chip. It provides for the kernel to enable cache Write Allocation for the L1 cache, which was disabled by default on these chips.
If you are running a workstation or server when you know that you will not be acting as an NFS server, you can add the above line to your kernel configuration to disable NFS server code. NFS servers allow other servers and workstations to mount parts of their filesystems using the Network FileSystem protocol.
Another way of saving kernel memory is to define the maximum number of swap devices. Your kernel needs to allocate a fixed amount of bit-mapped memory so that it can interleave swap devices. I set the preceding parameter to 1 on my workstation and 2 on my servers. I rarely run out of swap space on a workstation but if I need to add more to a server, I can easily create another partition
Another option you have when compiling your kernel is to build with the debugging symbols. This can be fundamental in determining the reason your kernel panics, if it does. Be warned though - compilation time can increase slightly when doing this. To make a debug kernel, add the following line to your kernel configuration:
This doesn't actually install a kernel with full debugging symbols as /kernel. The /kernel
that gets installed is the stripped down regular kernel, but a separate kernel.debug file is
/usr/src/sys/compile/Your_Kernel_Name/kernel.debug. If your kernel panics and
leaves behind a core file, the kernel.debug file is used to get the debugging symbols when you
actually do the debug. See the OnLamp article for more on this.
One final thing you need to do if you're going to be building a debug kernel, is to have your system actually dump the memory to the swap partition. You can do this by adding the following like to /etc/rc.conf and rebooting:
Where "/dev/ad0s1b" is your swap partition as defined in /etc/fstab.
NOTE: Your swap partition needs to be at least 1Mb (1024Kb) bigger than your total amount of memory. When your system crashes, the memory will get dumped to your swap partition. When your system returns, your swap partition will be enabled and your disks will be
they are mounted. During this process, fsck uses a small amount of swap space. It would be
preferable if you had twice as much swap space as memory in this situation.
WraithNet is a personally run network for free web hosting for anyone publishing documents
or data relating to the open-source community.
If you would like a sub-domain for your mail and web pages, send an email to:
This is a list of references I found when writing this paper. Most of them contain much more detail on their particular subject than I have provided here. Hopefully they will be as useful to you as they were to me.
If you find a problem with this website, please email:
|Counter: 174827 page|
|views since Dec 2002|