[netperf-dev] netperf2 commit notice r300 - in trunk: . doc src
raj at netperf.org
raj at netperf.org
Wed May 27 14:49:43 PDT 2009
Author: raj
Date: 2009-05-27 14:49:42 -0700 (Wed, 27 May 2009)
New Revision: 300
Modified:
trunk/AUTHORS
trunk/Release_Notes
trunk/doc/netperf.info
trunk/src/netcpu_procstat.c
Log:
procstat fixes from andrew
Modified: trunk/AUTHORS
===================================================================
--- trunk/AUTHORS 2009-04-07 22:44:13 UTC (rev 299)
+++ trunk/AUTHORS 2009-05-27 21:49:42 UTC (rev 300)
@@ -104,6 +104,7 @@
for assistance with the FreeBSD sysctl() stuff, and later making it
calibration-free
fixes to configure to recognize Solaris 11
+fixes to netcpu_procstat.c for later linux kernels
Mark Cooper
pointing-out the need for -lresolv when compiling -DDO_DNS on RedHat
@@ -230,4 +231,4 @@
MingW cnd MSDOS (djgpp) leanups.
Marcel Shuldman
-Changes to make netperf more profiling friendly
\ No newline at end of file
+Changes to make netperf more profiling friendly
Modified: trunk/Release_Notes
===================================================================
--- trunk/Release_Notes 2009-04-07 22:44:13 UTC (rev 299)
+++ trunk/Release_Notes 2009-05-27 21:49:42 UTC (rev 300)
@@ -2,6 +2,9 @@
Things changed in this release:
+*) Fixes for Linux procstat-based CPU utilization on newer kernels
+ from Andrew Gallatin.
+
*) Fix for a TCP_RR hang from Michael Shuldman
*) Compilation cleanups for MingW cnd MSDOS (djgpp) ourtesy of Gisle
Modified: trunk/doc/netperf.info
===================================================================
--- trunk/doc/netperf.info 2009-04-07 22:44:13 UTC (rev 299)
+++ trunk/doc/netperf.info 2009-05-27 21:49:42 UTC (rev 300)
@@ -2656,8 +2656,8 @@
Netperf4 is the shorthand name given to version 4.X.X of netperf. This
is really a separate benchmark more than a newer version of netperf,
but it is a decendant of netperf so the netperf name is kept. The
-facitious way to describe netperf4 is to say it is the
-egg-laying-wolly-milk-pig version of netperf :) The more respectful
+facetious way to describe netperf4 is to say it is the
+egg-laying-woolly-milk-pig version of netperf :) The more respectful
way to describe it is to say it is the version of netperf with support
for synchronized, multiple-thread, multiple-test, multiple-system,
network-oriented benchmarking.
@@ -2853,7 +2853,7 @@
Node: Address Resolution114090
Node: Enhancing Netperf116066
Node: Netperf4117303
-Node: Concept Index118212
-Node: Option Index120602
+Node: Concept Index118213
+Node: Option Index120603
End Tag Table
Modified: trunk/src/netcpu_procstat.c
===================================================================
--- trunk/src/netcpu_procstat.c 2009-04-07 22:44:13 UTC (rev 299)
+++ trunk/src/netcpu_procstat.c 2009-05-27 21:49:42 UTC (rev 300)
@@ -40,12 +40,29 @@
idle. The rate at which this increments during a test is compared
with a previous calibrarion to arrive at a CPU utilization
percentage. raj 2005-01-26 */
-static uint64_t lib_start_count[MAXCPUS];
-static uint64_t lib_end_count[MAXCPUS];
+#define IDLE_IDX 4
+#define CPU_STATES 9
+typedef struct cpu_states
+{
+ uint64_t user;
+ uint64_t nice;
+ uint64_t sys;
+ uint64_t idle;
+ uint64_t iowait;
+ uint64_t hard_irq;
+ uint64_t soft_irq;
+ uint64_t steal;
+ uint64_t guest;
+} cpu_states_t;
+
+static cpu_states_t lib_start_count[MAXCPUS];
+static cpu_states_t lib_end_count[MAXCPUS];
+
+
/* The max. length of one line of /proc/stat cpu output */
-#define CPU_LINE_LENGTH ((8 * sizeof (long) / 3 + 1) * 4 + 8)
+#define CPU_LINE_LENGTH ((CPU_STATES * sizeof (long) / 3 + 1) * 4 + 8)
#define PROC_STAT_FILE_NAME "/proc/stat"
#define N_CPU_LINES(nr) (nr == 1 ? 1 : 1 + nr)
@@ -140,8 +157,8 @@
return sysconf (_SC_CLK_TCK);
}
-void
-get_cpu_idle (uint64_t *res)
+static void
+get_cpu (cpu_states_t *res)
{
int space;
int i;
@@ -158,15 +175,31 @@
/* Skip first line (total) on SMP */
if (n > 1) p = strchr (p, '\n');
- /* Idle time is the 4th space-separated token */
for (i = 0; i < n; i++) {
- for (space = 0; space < 4; space ++) {
- p = strchr (p, ' ');
- while (*++p == ' ');
- };
- res[i] = strtoul (p, &p, 10);
+ memset(&res[i], 0, sizeof (&res[i]));
+ p = strchr (p, ' ');
+ sscanf(p, "%llu %llu %llu %llu %llu %llu %llu %llu %llu",
+ (unsigned long long *)&res[i].user,
+ (unsigned long long *)&res[i].nice,
+ (unsigned long long *)&res[i].sys,
+ (unsigned long long *)&res[i].idle,
+ (unsigned long long *)&res[i].iowait,
+ (unsigned long long *)&res[i].hard_irq,
+ (unsigned long long *)&res[i].soft_irq,
+ (unsigned long long *)&res[i].steal,
+ (unsigned long long *)&res[i].guest);
if (debug) {
- fprintf(where,"res[%d] is %llu\n",i,res[i]);
+ fprintf(where,"res[%d] is %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
+ i,
+ (unsigned long long)res[i].user,
+ (unsigned long long)res[i].nice,
+ (unsigned long long)res[i].sys,
+ (unsigned long long)res[i].idle,
+ (unsigned long long)res[i].iowait,
+ (unsigned long long)res[i].hard_irq,
+ (unsigned long long)res[i].soft_irq,
+ (unsigned long long)res[i].steal,
+ (unsigned long long)res[i].guest);
fflush(where);
}
p = strchr (p, '\n');
@@ -181,30 +214,50 @@
measure_cpu_start()
{
cpu_method = PROC_STAT;
- get_cpu_idle(lib_start_count);
+ get_cpu(lib_start_count);
}
/* collect final CPU utilization raw data */
void
measure_cpu_stop()
{
- get_cpu_idle(lib_end_count);
+ get_cpu(lib_end_count);
}
+static uint64_t
+tick_subtract(uint64_t start, uint64_t end)
+{
+ uint64_t ret;
+
+ if (end >= start || (start & 0xffffffff00000000ULL))
+ return (end - start);
+
+ /*
+ * We wrapped, and it is likely that the kernel is suppling 32-bit
+ * counters, because "start" is less than 32-bits wide. If that's
+ * the case, then handle the wrap by subtracting off everything but
+ * the lower 32-bits so as to get back to unsigned 32-bit
+ * arithmetic.
+ */
+ return (end - start + 0xffffffff00000000ULL);
+}
+
float
calc_cpu_util_internal(float elapsed_time)
{
- int i;
+ int i, j;
- float actual_rate;
float correction_factor;
+ cpu_states_t diff;
+ uint64_t total_ticks;
lib_local_cpu_util = (float)0.0;
- /* It is possible that the library measured a time other than */
- /* the one that the user want for the cpu utilization */
- /* calculations - for example, tests that were ended by */
- /* watchdog timers such as the udp stream test. We let these */
- /* tests tell up what the elapsed time should be. */
+
+ /* It is possible that the library measured a time other than the
+ one that the user want for the cpu utilization calculations - for
+ example, tests that were ended by watchdog timers such as the udp
+ stream test. We let these tests tell up what the elapsed time
+ should be. */
if (elapsed_time != 0.0) {
correction_factor = (float) 1.0 +
@@ -214,6 +267,10 @@
correction_factor = (float) 1.0;
}
+ if (debug) {
+ fprintf(where,
+ "lib_local_maxrate = %f\n", lib_local_maxrate);
+ }
for (i = 0; i < lib_num_loc_cpus; i++) {
/* it would appear that on some systems, in loopback, nice is
@@ -222,25 +279,55 @@
does not go south. raj 6/95 and if we run completely out of idle,
the same thing could in theory happen to the USE_KSTAT path. raj
8/2000 */
-
- if (lib_end_count[i] == lib_start_count[i]) {
- lib_end_count[i]++;
+
+ /* Find the difference in all CPU stat fields */
+ diff.user =
+ tick_subtract(lib_start_count[i].user, lib_end_count[i].user);
+ diff.nice =
+ tick_subtract(lib_start_count[i].nice, lib_end_count[i].nice);
+ diff.sys =
+ tick_subtract(lib_start_count[i].sys, lib_end_count[i].sys);
+ diff.idle =
+ tick_subtract(lib_start_count[i].idle, lib_end_count[i].idle);
+ diff.iowait =
+ tick_subtract(lib_start_count[i].iowait, lib_end_count[i].iowait);
+ diff.hard_irq =
+ tick_subtract(lib_start_count[i].hard_irq, lib_end_count[i].hard_irq);
+ diff.soft_irq =
+ tick_subtract(lib_start_count[i].soft_irq, lib_end_count[i].soft_irq);
+ diff.steal =
+ tick_subtract(lib_start_count[i].steal, lib_end_count[i].steal);
+ diff.guest =
+ tick_subtract(lib_start_count[i].guest, lib_end_count[i].guest);
+ total_ticks = diff.user + diff.nice + diff.sys + diff.idle + diff.iowait
+ + diff.hard_irq + diff.soft_irq + diff.steal + diff.guest;
+
+ /* calculate idle time as a percentage of all CPU states */
+ if (total_ticks == 0) {
+ fprintf(stderr, "Total ticks 0 on CPU %d, charging nothing!\n", i);
+ lib_local_per_cpu_util[i] = 100.0;
+ } else {
+ lib_local_per_cpu_util[i] = 100.0 *
+ ((float) diff.idle / (float) total_ticks);
}
-
- actual_rate = (lib_end_count[i] > lib_start_count[i]) ?
- (float)(lib_end_count[i] - lib_start_count[i])/lib_elapsed :
- (float)(lib_end_count[i] - lib_start_count[i] +
- MAXLONG)/ lib_elapsed;
- lib_local_per_cpu_util[i] = (lib_local_maxrate - actual_rate) /
- lib_local_maxrate * 100;
+ /* invert percentage to reflect non-idle time */
+ lib_local_per_cpu_util[i] = 100.0 - lib_local_per_cpu_util[i];
+
+ /* apply correction factor */
lib_local_per_cpu_util[i] *= correction_factor;
if (debug) {
fprintf(where,
- "calc_cpu_util: actual_rate on processor %d is %f start %llx end %llx util %f cf %f\n",
+ "calc_cpu_util: util on processor %d, diff = %llu %llu %llu %llu %llu %llu %llu %llu %llu util %f cf %f\n",
i,
- actual_rate,
- lib_start_count[i],
- lib_end_count[i],
+ (unsigned long long)diff.user,
+ (unsigned long long)diff.nice,
+ (unsigned long long)diff.sys,
+ (unsigned long long)diff.idle,
+ (unsigned long long)diff.iowait,
+ (unsigned long long)diff.hard_irq,
+ (unsigned long long)diff.soft_irq,
+ (unsigned long long)diff.steal,
+ (unsigned long long)diff.guest,
lib_local_per_cpu_util[i],
correction_factor);
}
@@ -255,12 +342,12 @@
void
cpu_start_internal(void)
{
- get_cpu_idle(lib_start_count);
+ get_cpu(lib_start_count);
return;
}
void
cpu_stop_internal(void)
{
- get_cpu_idle(lib_end_count);
+ get_cpu(lib_end_count);
}
More information about the netperf-dev
mailing list