Re: How is loadavg calculated?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux