[Exim] Performance Improvements for Exim on Linux

Inizio della pagina
Delete this message
Reply to this message
Autore: Steven Clarke
Data:  
To: exim-users
Oggetto: [Exim] Performance Improvements for Exim on Linux
We've come across a substantial performance problem experienced by exim
under linux with load limits enabled. This patches increase mail
throughput by a factor of 4 on our test servers.

The patch is for 3.13 but should work fine on any recent source tree. It
is in the linux specific code so will have no impact on other systems.

Steve Clarke


--- exim-3.13/OS/os.c-Linux.old    Thu Jan 13 15:00:09 2000
+++ exim-3.13/OS/os.c-Linux    Tue Jul 18 22:18:44 2000
@@ -13,14 +13,25 @@
 #define OS_LOAD_AVERAGE



-/* This code is apparently the best way of getting the load average
-in Linux. */
+/* Linux has 2 ways of returning load average:
+
+     1) Do a read on /proc/loadavg
+     2) Use the sysinfo library function and syscall
+
+The latter is simpler but in Linux 2.0 - 2.2 (and probably later
releases)
+is exceptionally slow - 10-50ms per call is not unusual and about 100x
+slow the first method. This cripples high performance mail servers by
+increasing CPU utilisation by 3-5x.
+
+In exim's very early days, it used the 1st method. Later, it switched
to
+the 2nd method. Now it tries the 1st method and falls back to the 2nd
if
+/proc is unavailable. */


#include <linux/kernel.h>
#include <linux/sys.h>

int
-os_getloadavg(void)
+linux_slow_getloadavg(void)
{
struct sysinfo s;
double avg;
@@ -29,12 +40,6 @@
return (int)(avg * 1000.0);
}

-
-/* This code was previously used, but I'm told it isn't as good
-as the method above, so comment it out - but keep it, just in case
-some system needs it. Linux has many incarnations. You never know. */
-
-#ifdef never
int
os_getloadavg(void)
{
@@ -42,14 +47,13 @@
double avg;
int count;
int fd = open ("/proc/loadavg", O_RDONLY);
-if (fd == -1) return -1;
+if (fd == -1) return linux_slow_getloadavg();
count = read (fd, buffer, sizeof(buffer));
(void)close (fd);
-if (count <= 0) return -1;
+if (count <= 0) return linux_slow_getloadavg();
count = sscanf (buffer, "%lf", &avg);
-if (count < 1) return -1;
+if (count < 1) return linux_slow_getloadavg();
return (int)(avg * 1000.0);
}
-#endif

/* End of os.c-Linux */