Optimizing FreeBSD performance: kernel tuning with sysctl and loader.conf, monitoring with top, systat, vmstat, and iostat, and ZFS storage tuning with the ARC cache and recordsize. You will know which parameters to change and when the right time to change them is.

In the previous episode 17, you understood FreeBSD 15 and upgrade strategies. Now we enter the art of performance tuning — optimizing the system to use the resources available as efficiently as possible.
Tuning isn't about changing every parameter blindly. Good tuning starts from measurement — understanding where the bottleneck is — then changing the right parameter, and measuring again. This episode maps the measurement tools and the parameters you'll touch most often, including ZFS storage tuning.
Before touching any parameter, remember three principles:
sysctl.conf.sysctl -a | wc -l
sysctl kern.maxfilesFreeBSD exposes hundreds of runtime parameters. Knowing which ones are relevant is part of the craft.
A few parameters often changed in the kern and vm categories:
sysctl kern.maxfiles=100000
sysctl kern.maxfilesperproc=50000
sysctl vm.swap_idle_enabled=1kern.maxfiles raises the file descriptor limit — important for servers with many connections. vm.swap_idle_enabled slows the migration of idle processes to swap.
The TCP stack can be adjusted for network workloads:
sysctl net.inet.tcp.sendbuf_max=16777216
sysctl net.inet.tcp.recvbuf_max=16777216
sysctl net.inet.tcp.mssdflt=1460The buffer parameters determine how much data can be in transit before acknowledgement — a common bottleneck for large file transfers and many connections.
Info
Change TCP parameters only if measurements show a problem (for example, low throughput on high-latency connections). Changing buffers without data can actually waste kernel memory.
Parameters proven to work are written to /etc/sysctl.conf so they survive a reboot:
sysrc -f /etc/sysctl.conf kern.maxfiles=100000
sysrc -f /etc/sysctl.conf net.inet.tcp.sendbuf_max=16777216Kernel parameters that need to be set before boot (for example, those used while the kernel starts) are configured in /boot/loader.conf:
kern.maxfiles="100000"
kern.ipc.shmall="131072"Warning
Parameters in loader.conf are applied when the kernel boots — a reboot is required to apply them. This differs from sysctl, which can be changed at runtime. Good practice: test with sysctl first, then move to loader.conf or sysctl.conf once proven.
top shows processes and resource usage in real time, while systat provides statistics with a full-screen display:
top -o cpu
systat -vmstat
systat -ifstattop -o cpu sorts by CPU usage, systat -vmstat shows virtual memory, and systat -ifstat shows interface throughput.
Classic tools for measuring memory and I/O:
vmstat 1
iostat -w 1vmstat shows memory, swap, and CPU statistics. iostat shows throughput and disk utilization per device — important for detecting storage bottlenecks.
Success
A baseline routine: vmstat 1 for memory and CPU, iostat -w 1 for disks, systat -ifstat for the network. Collect a baseline before tuning — without one, you can't judge whether a change actually helped.
ARC is ZFS's cache in RAM. By default, ARC uses up to half of system memory. For machines with limited memory or large application needs, cap it:
sysctl vfs.zfs.arc_max=2147483648The value above caps ARC at 2 GB. Write it to sysctl.conf to make it persistent.
Warning
Reducing ARC too drastically will hurt repeated read performance. Start with a conservative limit and monitor with zpool iostat and arcstat to find the balance between ZFS cache and application memory.
recordsize controls ZFS's logical block size — affecting performance based on your I/O pattern:
zfs set recordsize=16k tank/data/db
zfs set recordsize=1M tank/data/mediaDatabases with small random access (like PostgreSQL) suit 16k or 8k. Large streaming media data suits big blocks like 1M — verify with zfs get recordsize.
lz4 and zstd compression (episodes 8-9) reduce actual I/O. Make sure it stays enabled for workloads that can be compressed.
FreeBSD uses a kernel-based I/O scheduler. For SSDs, make sure trim runs so long-term performance is preserved:
zpool get autotrimFollow a disciplined measurement cycle:
vmstat, iostat, systat.iostat -w 1
sysctl vfs.zfs.arc_max=2147483648
iostat -w 1
sysrc -f /etc/sysctl.conf vfs.zfs.arc_max=2147483648In this episode 18, you learned FreeBSD performance tuning: kernel tuning with sysctl and loader.conf, TCP and memory parameters, monitoring with top, systat, vmstat, and iostat, and ZFS storage tuning with ARC and recordsize.
Key takeaways:
kern.maxfiles and TCP buffers are common tuning points.vfs.zfs.arc_max.recordsize follows the I/O pattern: small for databases, large for streaming media.In the next episode, episode 19, we'll cover FreeBSD as a router, firewall & network appliance — the OPNsense and NAS use cases, running the Nginx, MySQL, PostgreSQL, and Redis stack, and reliable production web server deployment on top of FreeBSD.