Bug 69011 - Display IO-Wait time on 2.5/2.6 kernels
Summary: Display IO-Wait time on 2.5/2.6 kernels
Status: RESOLVED FIXED
Alias: None
Product: ksysguard
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: Gentoo Packages Linux
: NOR wishlist
Target Milestone: ---
Assignee: Greg Martyn
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-11-25 17:18 UTC by Ernst Bachmann
Modified: 2007-03-09 11:38 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments
adds a cpu-wait-cycles sensor to ksysguard (9.08 KB, patch)
2005-04-07 21:47 UTC, Benno Schulenberg
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ernst Bachmann 2003-11-25 17:18:16 UTC
Version:            (using KDE KDE 3.1.93)
Installed from:    Gentoo Packages
OS:          Linux

2.5/2.6 kernels distinguish between time spent in system/kernel code and io-wait time.
vmstat and top display it seperately.
Ksysguard does not offer an option to display it, even worse, it groups the IO-Wait time with the system load, which seems wrong to me, cause the time spent waiting for IO is more like idle time, as it could be used by other applications.
Comment 1 Benno Schulenberg 2005-04-07 21:47:44 UTC
Created attachment 10547 [details]
adds a cpu-wait-cycles sensor to ksysguard
Comment 2 Benno Schulenberg 2005-05-03 23:24:19 UTC
Any chance that this patch gets included?
Comment 3 Greg Martyn 2007-03-09 11:30:22 UTC
SVN commit 640862 by martyn:

BUG: 69011
Monitor cpu time spent waiting on I/O


 M  +4 -3      gui/KSysGuardApplet.xml  
 M  +4 -3      gui/SystemLoad.sgrd  
 M  +4 -3      gui/ksgrd/SensorManager.cc  
 M  +53 -10    ksysguardd/Linux/stat.c   [POSSIBLY UNSAFE: scanf]
 M  +4 -0      ksysguardd/Linux/stat.h  


--- trunk/KDE/kdebase/workspace/ksysguard/gui/KSysGuardApplet.xml #640861:640862
@@ -3,9 +3,10 @@
 <WorkSheet sizeRatio="1.2" dockCnt="2" interval="4" >
  <host port="-1" shell="" name="localhost" command="ksysguardd" />
  <display topBar="1" vColor="326429" title="CPU" dock="0" bColor="3223601" graphStyle="0" class="FancyPlotter" unit="" hScale="1" showUnit="0" hLines="1" hCount="2" vLines="1" autoRange="1" min="0" max="0" hColor="14606046" globalUpdate="1" pause="0" fontSize="8" labels="1" vScroll="1" vDistance="30" >
-  <beam sensorName="cpu/user" hostName="localhost" color="1608191" sensorType="integer" />
-  <beam sensorName="cpu/sys" hostName="localhost" color="16743688" sensorType="integer" />
-  <beam sensorName="cpu/nice" hostName="localhost" color="16771600" sensorType="integer" />
+  <beam sensorName="cpu/user" hostName="localhost" color="1608191" sensorType="float" />
+  <beam sensorName="cpu/sys" hostName="localhost" color="16743688" sensorType="float" />
+  <beam sensorName="cpu/nice" hostName="localhost" color="16771600" sensorType="float" />
+  <beam sensorName="cpu/wait" hostName="localhost" color="16764927" sensorType="float" />
  </display>
  <display topBar="1" vColor="4605510" title="Mem" dock="1" bColor="3223601" graphStyle="0" class="FancyPlotter" unit="" hScale="5" showUnit="0" hLines="1" hCount="2" vLines="0" autoRange="1" min="0" max="0" hColor="14606046" globalUpdate="1" pause="0" fontSize="8" labels="0" vScroll="1" vDistance="30" >
   <beam sensorName="mem/physical/application" hostName="localhost" color="1608191" sensorType="integer" />
--- trunk/KDE/kdebase/workspace/ksysguard/gui/SystemLoad.sgrd #640861:640862
@@ -3,9 +3,10 @@
 <WorkSheet title="Sensor Load" interval="2" locked="1" rows="2" columns="2" >
  <host port="-1" command="ksysguardd" shell="" name="localhost" />
  <display svgBackground="default_theme.svg" bColor="3223601" title="CPU Load" hScale="3" hCount="5" fontColor="16777215" max="100" vLines="1" hColor="0" pause="0" labels="1" autoRange="0" min="0" vDistance="30" globalUpdate="1" fontSize="11" vScroll="0" column="0" topBar="1" unit="" vColor="0" hLines="1" showUnit="1" class="FancyPlotter" row="0" >
-  <beam sensorName="cpu/nice" sensorType="integer" hostName="localhost" color="16776979" />  
-  <beam sensorName="cpu/user" sensorType="integer" hostName="localhost" color="1608191" />
-  <beam sensorName="cpu/sys" sensorType="integer" hostName="localhost" color="16743688" />
+  <beam sensorName="cpu/nice" sensorType="float" hostName="localhost" color="16776979" />  
+  <beam sensorName="cpu/user" sensorType="float" hostName="localhost" color="1608191" />
+  <beam sensorName="cpu/sys" sensorType="float" hostName="localhost" color="16743688" />
+  <beam sensorName="cpu/wait" sensorType="float" hostName="localhost" color="16764927" />
  </display>
  <display svgBackground="default_theme.svg" bColor="3223601" title="Load Average (1 min)" hScale="3" hCount="5" fontColor="16777215" vLines="1" hColor="0" pause="0" labels="1" autoRange="1" vDistance="30" globalUpdate="1" fontSize="11" vScroll="0" column="1" topBar="1" unit="" vColor="0" hLines="1" showUnit="1" class="FancyPlotter" row="0" >
   <beam sensorName="cpu/loadavg1" sensorType="float" hostName="localhost" color="1608191" />
--- trunk/KDE/kdebase/workspace/ksysguard/gui/ksgrd/SensorManager.cc #640861:640862
@@ -62,11 +62,12 @@
 {
   // Fill the sensor description dictionary.
   mDict.insert( QLatin1String( "cpu" ), i18n( "CPU Load" ) );
-  mDict.insert( QLatin1String( "idle" ), i18n( "Idle Load" ) );
+  mDict.insert( QLatin1String( "idle" ), i18n( "Idling" ) );
+  mDict.insert( QLatin1String( "nice" ), i18n( "Nice Load" ) );
+  mDict.insert( QLatin1String( "user" ), i18n( "User Load" ) );
   mDict.insert( QLatin1String( "sys" ), i18n( "System Load" ) );
-  mDict.insert( QLatin1String( "nice" ), i18n( "Nice Load" ) );
+  mDict.insert( QLatin1String( "wait" ), i18n( "Waiting" ) );
   mDict.insert( QLatin1String( "TotalLoad" ), i18n( "Total Load" ) );
-  mDict.insert( QLatin1String( "user" ), i18n( "User Load" ) );
   mDict.insert( QLatin1String( "mem" ), i18n( "Memory" ) );
   mDict.insert( QLatin1String( "physical" ), i18n( "Physical Memory" ) );
   mDict.insert( QLatin1String( "swap" ), i18n( "Swap Memory" ) );
--- trunk/KDE/kdebase/workspace/ksysguard/ksysguardd/Linux/stat.c #640861:640862
@@ -43,6 +43,7 @@
 	float niceLoad;
 	float sysLoad;
 	float idleLoad;
+	float waitLoad;
 	
 	/* To calculate the loads we need to remember the tick values for each
 	* load type. */
@@ -50,6 +51,7 @@
 	unsigned long niceTicks;
 	unsigned long sysTicks;
 	unsigned long idleTicks;
+	unsigned long waitTicks;
 } CPULoadInfo;
 
 typedef struct {
@@ -142,30 +144,33 @@
 }
 	
 static void updateCPULoad( const char* line, CPULoadInfo* load ) {
-	unsigned long currUserTicks, currSysTicks, currNiceTicks, currIdleTicks;
-	unsigned long totalTicks;
+	unsigned long currUserTicks, currSysTicks, currNiceTicks;
+	unsigned long currIdleTicks, currWaitTicks, totalTicks;
 	
-	sscanf( line, "%*s %lu %lu %lu %lu", &currUserTicks, &currNiceTicks,
-		&currSysTicks, &currIdleTicks );
+	sscanf( line, "%*s %lu %lu %lu %lu %lu", &currUserTicks, &currNiceTicks,
+		&currSysTicks, &currIdleTicks, &currWaitTicks );
 	
 	totalTicks = ( currUserTicks - load->userTicks ) +
 		( currSysTicks - load->sysTicks ) +
 		( currNiceTicks - load->niceTicks ) +
-		( currIdleTicks - load->idleTicks );
+		( currIdleTicks - load->idleTicks ) +
+		( currWaitTicks - load->waitTicks );
 	
 	if ( totalTicks > 10 ) {
 		load->userLoad = ( 100.0 * ( currUserTicks - load->userTicks ) ) / totalTicks;
 		load->sysLoad = ( 100.0 * ( currSysTicks - load->sysTicks ) ) / totalTicks;
 		load->niceLoad = ( 100.0 * ( currNiceTicks - load->niceTicks ) ) / totalTicks;
-		load->idleLoad = ( 100.0 - ( load->userLoad + load->sysLoad + load->niceLoad ) );
+		load->idleLoad = ( 100 * ( currIdleTicks - load->idleTicks ) ) / totalTicks;
+		load->waitLoad = ( 100 * ( currWaitTicks - load->waitTicks ) ) / totalTicks;
 	}
 	else
-		load->userLoad = load->sysLoad = load->niceLoad = load->idleLoad = 0.0;
+		load->userLoad = load->sysLoad = load->niceLoad = load->idleLoad = load->waitLoad = 0.0;
 		
 	load->userTicks = currUserTicks;
 	load->sysTicks = currSysTicks;
 	load->niceTicks = currNiceTicks;
 	load->idleTicks = currIdleTicks;
+	load->waitTicks = currWaitTicks;
 }
 	
 static int process24Disk( char* tag, char* buf, const char* label, int idx ) {
@@ -430,9 +435,9 @@
 
 void initStat( struct SensorModul* sm ) {
 	/* The CPU load is calculated from the values in /proc/stat. The cpu
-	* entry contains 4 counters. These counters count the number of ticks
+	* entry contains 7 counters. These counters count the number of ticks
 	* the system has spend on user processes, system processes, nice
-	* processes and idle time.
+	* processes, idle and IO-wait time, hard and soft interrupts.
 	*
 	* SMP systems will have cpu1 to cpuN lines right after the cpu info. The
 	* format is identical to cpu and reports the information for each cpu.
@@ -440,7 +445,7 @@
 	*
 	* The /proc/stat file looks like this:
 	*
-	* cpu  1586 4 808 36274
+	* cpu  <user> <nice> <system> <idling> <waiting> <hardinterrupt> <softinterrupt>
 	* disk 7797 0 0 0
 	* disk_rio 6889 0 0 0
 	* disk_wio 908 0 0 0
@@ -486,6 +491,7 @@
 			registerMonitor( "cpu/sys", "float", printCPUSys, printCPUSysInfo, StatSM );
 			registerMonitor( "cpu/TotalLoad", "float", printCPUTotalLoad, printCPUTotalLoadInfo, StatSM );
 			registerMonitor( "cpu/idle", "float", printCPUIdle, printCPUIdleInfo, StatSM );
+			registerMonitor( "cpu/wait", "float", printCPUWait, printCPUWaitInfo, StatSM );
 		}
 		else if ( strncmp( "cpu", tag, 3 ) == 0 ) {
 			char cmdName[ 24 ];
@@ -504,6 +510,8 @@
 			registerMonitor( cmdName, "float", printCPUxTotalLoad, printCPUxTotalLoadInfo, StatSM );
 			sprintf( cmdName, "cpu%d/idle", id );
 			registerMonitor( cmdName, "float", printCPUxIdle, printCPUxIdleInfo, StatSM );
+			sprintf( cmdName, "cpu%d/wait", id );
+			registerMonitor( cmdName, "float", printCPUxWait, printCPUxWaitInfo, StatSM );
 		}
 		else if ( strcmp( "disk", tag ) == 0 ) {
 			unsigned long val;
@@ -720,6 +728,22 @@
 	fprintf( CurrentClient, "CPU Idle Load\t0\t100\t%%\n" );
 }
 
+void printCPUWait( const char* cmd )
+{
+	(void)cmd;
+
+	if ( Dirty )
+		process24Stat();
+
+	fprintf( CurrentClient, "%f\n", CPULoad.waitLoad );
+}
+
+void printCPUWaitInfo( const char* cmd )
+{
+	(void)cmd;
+	fprintf( CurrentClient, "CPU Wait Load\t0\t100\t%%\n" );
+}
+
 void printCPUxUser( const char* cmd ) {
 	int id;
 	
@@ -805,6 +829,25 @@
 	fprintf( CurrentClient, "CPU%d Idle Load\t0\t100\t%%\n", id );
 }
 
+void printCPUxWait( const char* cmd )
+{
+	int id;
+
+	if ( Dirty )
+		process24Stat();
+
+	sscanf( cmd + 3, "%d", &id );
+	fprintf( CurrentClient, "%f\n", SMPLoad[ id ].waitLoad );
+}
+
+void printCPUxWaitInfo( const char* cmd )
+{
+	int id;
+
+	sscanf( cmd + 3, "%d", &id );
+	fprintf( CurrentClient, "CPU%d Wait Load\t0\t100\t%%\n", id );
+}
+
 void print24DiskTotal( const char* cmd ) {
 	int id;
 	
--- trunk/KDE/kdebase/workspace/ksysguard/ksysguardd/Linux/stat.h #640861:640862
@@ -36,6 +36,8 @@
 void printCPUTotalLoadInfo( const char* );
 void printCPUIdle( const char* );
 void printCPUIdleInfo( const char* );
+void printCPUWait( const char* );
+void printCPUWaitInfo( const char* );
 void printCPUxUser( const char* );
 void printCPUxUserInfo( const char* );
 void printCPUxNice( const char* );
@@ -46,6 +48,8 @@
 void printCPUxTotalLoadInfo( const char* );
 void printCPUxIdle( const char* );
 void printCPUxIdleInfo( const char* );
+void printCPUxWait( const char* );
+void printCPUxWaitInfo( const char* );
 void print24DiskIO( const char* cmd );
 void print24DiskIOInfo( const char* cmd );
 void print24DiskTotal( const char* );
Comment 4 Greg Martyn 2007-03-09 11:38:42 UTC
Thanks for the patch; sorry it took so long