Skip to content

Breaking File Descriptor Barriers

Lloyd Dilley edited this page Mar 8, 2015 · 2 revisions

Breaking File Descriptor Barriers

If you maintain a small IRC network or are using EventMachine with epoll() or kqueue() (once support for EM is added!), then you do not need to worry about this guide. However, if you want to do some stress testing or can actually achieve >1024 simultaneous connections using RubIRCd, then this guide is for you. Each operating system has a ceiling for the number of open files a user can have at a time. On certain distributions of Linux for example, the default soft limit is 1024. If you happen to hit around 1024 simultaneous connections, RubIRCd will not be able to accept any additional clients. Before showing you various ways to increase this cap, you need to remember to bump up the max_connections value in the options.yml file under the cfg/ directory. Set this value to something beyond 1024 obviously.

Now, keep in mind that there are soft and hard limits. The soft limit is what is enforced initially and a user is allowed to increase the soft limit to match the hard limit set by the OS or root. Check the table below to see how to raise the descriptors/nofile value for your respective shell.

Description csh/tcsh sh/bash/ksh
Show all limits limit ulimit -a
Show only descriptors/nofile soft limit limit descriptors ulimit -n or ulimit -Sn
Show only descriptors/nofile hard limit limit -h descriptors ulimit -Hn
Set new descriptors/nofile soft limit limit descriptors 2048 ulimit -n 2048

Modifying the value in this manner from the table above will only persist for the session. Once you log out of the shell, the settings revert. You need to add the appropriate line to your shell's profile to make it stick. It is important again to emphasize that you cannot exceed the hard limit. If you need more than the hard limit (currently 4096 on my system by default) allows, then read below. The hard limit should at least match the value of the soft limit. This guide does not cover how to increase the system-wide limit for total file descriptors. Unless you have a bunch of other things running on your system, then the default system-wide limit should be generous enough in most cases.

AIX

Modify the nofiles value in the /etc/security/limits file. You can make the file look like below to have per-user settings:

ircd:
          nofiles = 2048

or:

chuser nofiles=2048 ircd

If you do not specify the user in /etc/security/limits, then the setting will be the default for everyone. No reboot is required. Log back in and you should be good to go. For reference, nofiles_hard is the hard limit and should already be significantly higher than what you'll need. It matches the OPEN_MAX constant from limits.h and should be around ~32K, 65534, or reported by ulimit to be "unlimited".

FreeBSD

On recent releases of FreeBSD, the soft limit seems to match the hard limit which also happens to match the system limit. This is from my FreeBSD 9.1 system:

ldilley@daemon:/home/ldilley % sysctl -a | grep maxfiles
kern.maxfiles: 12328
kern.maxfilesperproc: 11095
ldilley@daemon:/home/ldilley % limit descriptors
descriptors  11095 
ldilley@daemon:/home/ldilley % limit -h descriptors
descriptors  11095

One thing that should change though is the size of the TCP listen queue:

ldilley@daemon:/home/ldilley % sysctl -a | grep somax
kern.ipc.somaxconn: 128

The FreeBSD manual recommends raising this value to 1024 or higher. You can do this by modifying /etc/sysctl.conf to include:

kern.ipc.somaxconn=2048

This will allow the change to persist across reboots. To make it active now:

sysctl kern.ipc.somaxconn=2048

HP-UX

Check existing values on 11.11 (11iv1):

kctune -q mayflies
kctune -q maxfiles_lim

Check existing values on 11.23 (11iv2) and 11.31 (11iv3):

kctune maxfiles
kctune maxfiles_lim

Set values on 11.11 (11iv1):

kctune -s maxfiles=2048
kctune -s maxfiles_lim=4096

Set values on 11.23 (11iv2) and 11.31 (11iv3):

kctune maxfiles=2048
kctune maxfiles_lim=4096

No reboot is required to make the changes take effect. maxfiles is the soft limit and maxfiles_lim is the hard limit.

Linux

Edit /etc/security/limits.conf and add something like the following:

ircd               soft    nofile            2048
ircd               hard    nofile            4096

You can replace "ircd" with any user you would like or '*' for all users. Log out and back in to make the new settings take effect.

OS X

The hard limit for open files on OS X 10.8.5 shows "unlimited" while using my regular account. The soft limit is set to 256. This is a similar situation to Solaris below. Unfortunately, the OS does not allow me to increase my soft limit beyond 1024 despite the hard limit being unlimited. File descriptor limits for users are controlled by launchd. You can get at the values like so:

mini:~ ldilley$ launchctl limit maxfiles
	maxfiles    256            unlimited

Use the command below to set the base soft limit to 2048 in /etc/launchd.conf (this requires a reboot!):

echo "limit maxfiles 2048 unlimited" | sudo tee -a /etc/launchd.conf

When the system comes back up, check your ulimit to see if the change worked. Lastly, since OS X is based on FreeBSD, we will likely want to increase kern.ipc.somaxconn (TCP listen queue) from the default 128 to 2048:

sudo sysctl -w kern.ipc.somaxconn=2048
echo "kern.ipc.somaxconn=2048" | sudo tee -a /etc/sysctl.conf

The last command will make the change permanent.

Solaris

On Solaris 10 u11 (and likely others), the hard limit for descriptors is a whopping 65536 for non-root users even. The soft limit is only a mere 256 however. To change this, you can either use projects (/etc/project) or simply execute the following:

ulimit -n 2048

Don't forget to add the same command to your shell's profile to make it permanent.

Windows

The stdio-level limit (soft) seems to be 512. The lowio-level limit (hard) is 2048. The lowio limit cannot be increased. The stdio limit can be increased up to the lowio limit by using a C/C++ program and calling:

_setmaxstdio(2048); 

If all went well, the function should return "2048". "-1" is returned on failure. You can also call the following function to check what the current limit is:

_getmaxstdio();

Example code is below:

#include 

int main(void)
{
  printf("Current limit: %d\n", _getmaxstdio());
  _setmaxstdio(2048);
  printf("New limit: %d\n", _getmaxstdio());
  return 0;
}
Clone this wiki locally