Here - suitably mangled by my mailer - is a patch I wrote against 2.4.9 that gives you a file /proc/loadstat containing the last 180 actual counts of the runqueue, so you may compute _actual_ yourslef rather than relying on the estimated load averages provided by the system? The system load averages are in fact quite good when the load is stable, but the minute it begins to change it tends to lag behind when it is rising and "lag ahead" when it is falling, sometimes by several minutes. --- /usr/src/linux-2.4.9 old/Documentation/filesystems/proc.txt Fri Apr 6 13:42:48 2001 +++ /usr/src/linux-2.4.9-new/Documentation/filesystems/proc.txt Thu Sep 20 21:50:35 2001 @@ -220,6 +220,7 @@ partitions Table of partitions known to the system pci Depreciated info of PCI bus (new way -> /proc/bus/pci/, decoupled by lspci (2.4) + loadstat Counts of active processes for load testing rtc Real time clock scsi SCSI info (see text) slabinfo Slab pool info @@ -326,7 +327,23 @@ Commonly used objects have their own slab pool (such as network buffers, directory cache, and so on). -1.3 IDE devices in /proc/ide +/proc/loadstat preserves the sampling data used to build /proc/loadavg. This +data is otherwise discarded by the kernel after each five second interval. +The built-in load average algorithm is completely adequate over a long +period of time, or when the load is changing slowly. However when the load +is rising or falling quickly, the builtin algorithm has a tendency to lag +behind when it is rising, and "lag ahead" when it is falling, sometimes by +a significant amount. Moreover /proc/loadstat make it possible to compute +the load averages on a different basis from the standard 1/5/15 minute periods. + +The values output from the loadstat file are given newest first, which is +handy for computing load averages on the fly. The precision of these numbers +is limited by the size of the elements of the array used to hold the data. +In the current implementation this is 'u8' which creates a ceiling of 255 +processes counted per interval. However this may be trivially redefined +in include/linux/sched.h. + +1.3 IDE devices in /proc/ide. ---------------------------- The subdirectory /proc/ide contains information about all IDE devices of which --- /usr/src/linux-2.4.9-old/include/linux/sched.h Wed Aug 15 17:21:11 2001 +++ /usr/src/linux-2.4.9-new/include/linux/sched.h Thu Sep 20 21:39:28 2001 @@ -55,6 +55,7 @@ */ extern unsigned long avenrun[]; /* Load averages */ +//if any of these change then adjust LDA_SIZE as required #define FSHIFT 11 /* nr of bits of precision */ #define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */ #define LOAD_FREQ (5*HZ) /* 5 sec intervals */ @@ -66,6 +67,13 @@ load *= exp; \ load += n*(FIXED_1-exp); \ load >>= FSHIFT; + +//for more precision redefine ldstat_type and LDA_BITS +typedef u8 ldstat_type; +#define LDA_BITS 8 +#define LDA_SIZE 180 +#define LDA_EXP (1<<LDA_BITS) +#define LDA_MAX ((unsigned long)(LDA_EXP-1)) #define CT_TO_SECS(x) ((x) / HZ) #define CT_TO_USECS(x) (((x) % HZ) * 1000000/HZ) --- /usr/src/linux-2.4.9-old/kernel/timer.c Tue Jun 12 19:40:11 2001 +++ /usr/src/linux-2.4.9-new/kernel/timer.c Thu Sep 20 21:55:35 2001 @@ -622,8 +622,12 @@ */ unsigned long avenrun[3]; +ldstat_type ldstats[LDA_SIZE]={0,}; +int ldstat_idx=0; + static inline void calc_load(unsigned long ticks) { + unsigned long tmp; unsigned long active_tasks; /* fixed-point */ static int count = LOAD_FREQ; @@ -631,6 +635,14 @@ if (count < 0) { count += LOAD_FREQ; active_tasks = count_active_tasks(); + + //convert from fixed point + tmp=active_tasks>>FSHIFT; + tmp=min(unsigned long,LDA_MAX,tmp); + if(--ldstat_idx<0) + ldstat_idx=LDA_SIZE-1; + ldstats[ldstat_idx]=(ldstat_type)tmp; + CALC_LOAD(avenrun[0], EXP_1, active_tasks); CALC_LOAD(avenrun[1], EXP_5, active_tasks); CALC_LOAD(avenrun[2], EXP_15, active_tasks); --- /usr/src/linux-2.4.9-old/fs/proc/proc_misc.c Sat Jul 7 14:43:24 2001 +++ /usr/src/linux-2.4.9-new/fs/proc/proc_misc.c Thu Sep 20 21:57:04 2001 @@ -100,6 +100,28 @@ return proc_calc_metrics(page, start, off, count, eof, len); } +extern int ldstat_idx; +extern ldstat_type ldstats[]; + +static int loadstat_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) + { + int pg_offset = 0; + int i = ldstat_idx; + int xcount; + + //leave nprocs type 'unsigned long' so we can always + //redefine ldstat_type upward without truncation errors + unsigned long nprocs; + + for(xcount=0;xcount<LDA_SIZE;xcount++) + { + nprocs=(unsigned long)ldstats[i++%LDA_SIZE]; + pg_offset+=sprintf(page+pg_offset,"%lu\n",nprocs); + } + return proc_calc_metrics(page, start, off, count, eof, pg_offset); + } + static int uptime_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -516,6 +538,7 @@ int (*read_proc)(char*,char**,off_t,int,int*,void*); } *p, simple_ones[] = { {"loadavg", loadavg_read_proc}, + {"loadstat", loadstat_read_proc}, {"uptime", uptime_read_proc}, {"meminfo", meminfo_read_proc}, {"version", version_read_proc}, __________________________________________________ Do You Yahoo!? Send FREE video emails in Yahoo! Mail! http://promo.yahoo.com/videomail/ -- Kernelnewbies: Help each other learn about the Linux kernel. Archive: http://mail.nl.linux.org/kernelnewbies/ IRC Channel: irc.openprojects.net / #kernelnewbies Web Page: http://www.kernelnewbies.org/