[ipxe-devel] [patch] preserve CPU in virtualized environment.

Alessandro Salvatori sandr8 at gmail.com
Mon Jul 16 09:50:36 UTC 2012


Hello,

  my company (Embrane) kindly allowed me to contribute this patch upstream.

The patch is very simple, and brings the CPU utilization down from 100% to 1-3%,
while not affecting the throughput in any perceivable way. There might be better
solutions, but this only took me half an hour to write and test, and seemed good
enough for us.

thank you!
-Alessandro-
 Here i am, A young man,
 A crashing computer program,
 Here is a pen, write out my name...

(from: The Servant - Orchestra)

#---------------8<---[snip]---------------------------------------------------------------------------------
# create a permanent sleeping beauty process that sleeps 1/18.2th of second
# every four times it gets scheduled, unless the do_not_sleep flag is set.
# the do_not_sleep flag is meant to be set when a download is in progress,
# so that the download throughput is not affected.
#---------------8<---[snip]---------------------------------------------------------------------------------
--- a/src/usr/sleeping_beauty.c	1969-12-31 16:00:00.000000000 -0800
+++ b/src/usr/sleeping_beauty.c	2012-06-25 15:27:46.607097999 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 Embrane, Inc. <alessandro.salvatori at embrane.com>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/process.h>
+#include <ipxe/nap.h>
+#include <usr/sleeping_beauty.h>
+
+
+
+#define SLEEPING_FACTOR 4
+
+static int do_not_sleep = 0;
+
+void prince_kisses_sleeping_beauty(void) {
+	do_not_sleep = 1;
+}
+
+void sleeping_beauty_bites_the_apple(void) {
+	do_not_sleep = 0;
+}
+
+/**
+ * Sleep every SLEEPING_FACTOR times
+ *
+ * @v process		Network stack process
+ */
+static void sleeping_step ( struct process *process __unused ) {
+	static int countdown = 0;
+
+	if ( 0 == countdown ) {
+		countdown = SLEEPING_FACTOR;
+	}
+
+	if ( do_not_sleep || --countdown ) {
+		return;
+	}
+
+	cpu_nap();
+}
+
+/* Sleeping beauty process */
+PERMANENT_PROCESS ( sleeping_beauty, sleeping_step );
#---------------8<---[snip]---------------------------------------------------------------------------------
# make two methods available to toggle the aggressive polling on and off:
#
# - prince_kisses_sleeping_beauty()   <-- the beauty wakes up and
polls agressively
#
# - sleeping_beauty_bites_the_apple() <-- the beauty falls asleep
again and uses very little CPU
#
#---------------8<---[snip]---------------------------------------------------------------------------------
--- a/src/usr/sleeping_beauty.h	1969-12-31 16:00:00.000000000 -0800
+++ b/src/usr/sleeping_beauty.h	2012-06-25 15:27:17.118098360 -0700
@@ -0,0 +1,3 @@
+extern void prince_kisses_sleeping_beauty(void);
+
+extern void sleeping_beauty_bites_the_apple(void);
#---------------8<---[snip]---------------------------------------------------------------------------------
# Detect when TCP connections stall, and fail the download, else from there
# on we would be sucking the host CPU forever.
#---------------8<---[snip]---------------------------------------------------------------------------------
diff --git a/src/core/monojob.c b/src/core/monojob.c
index d2161b3..9bcb943 100644
--- a/src/core/monojob.c
+++ b/src/core/monojob.c
@@ -67,6 +67,8 @@ int monojob_wait ( const char *string ) {
 	unsigned long completed;
 	unsigned long total;
 	unsigned int percentage;
+	unsigned long last_completed = 0;
+	unsigned int stalled_seconds = 0;
 	int shown_percentage = 0;

 	if ( string )
@@ -102,6 +104,15 @@ int monojob_wait ( const char *string ) {
 			if ( shown_percentage )
 				printf ( "\b\b\b\b    \b\b\b\b" );
 			job_progress ( &monojob, &progress );
+			if ( last_completed == progress.completed ) {
+				++stalled_seconds;
+			} else {
+				stalled_seconds=0;
+			}
+			if ( stalled_seconds >= 30 ) {
+				monojob_close ( &monojob, -ETIME );
+				break;
+			}
 			/* Normalise progress figures to avoid overflow */
 			completed = ( progress.completed / 128 );
 			total = ( progress.total / 128 );
@@ -113,6 +124,7 @@ int monojob_wait ( const char *string ) {
 				printf ( "." );
 				shown_percentage = 0;
 			}
+			last_completed = progress.completed;
 			last_progress = now;
 		}
 	}
#---------------8<---[snip]---------------------------------------------------------------------------------
# Avoid using 100% CPU at all times (bad for virtualized environments).
# When a download making progress, go back to aggressive polling
#---------------8<---[snip]---------------------------------------------------------------------------------
diff -u b/src/core/monojob.c b/src/core/monojob.c
--- a/src/core/monojob.c
+++ b/src/core/monojob.c
@@ -27,6 +27,7 @@
 #include <ipxe/job.h>
 #include <ipxe/monojob.h>
 #include <ipxe/timer.h>
+#include <usr/sleeping_beauty.h>

 /** @file
  *
@@ -104,6 +105,9 @@
 			if ( shown_percentage )
 				printf ( "\b\b\b\b    \b\b\b\b" );
 			job_progress ( &monojob, &progress );
+			if ( progress.completed && !last_completed ) {
+				prince_kisses_sleeping_beauty();
+			}
 			if ( last_completed == progress.completed ) {
 				++stalled_seconds;
 			} else {
#---------------8<---[snip]---------------------------------------------------------------------------------
# Avoid using 100% CPU at all times (bad for virtualized environments).
# When a download fails, go back to moderate polling
#---------------8<---[snip]---------------------------------------------------------------------------------
--- a/src/usr/autoboot.c
+++ b/src/usr/autoboot.c
@@ -34,6 +34,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <usr/dhcpmgmt.h>
 #include <usr/imgmgmt.h>
 #include <usr/autoboot.h>
+#include <usr/sleeping_beauty.h>

 /** @file
  *
@@ -396,6 +397,9 @@ int netboot ( struct net_device *netdev ) {
  err_pxe_menu_boot:
  err_dhcp:
  err_ifopen:
+
+	sleeping_beauty_bites_the_apple();
+
 	return rc;
 }

#---------------8<---[snip]---------------------------------------------------------------------------------
-------------- next part --------------
A non-text attachment was scrubbed...
Name: sleeping_beauty.patch
Type: application/octet-stream
Size: 6109 bytes
Desc: not available
URL: <http://lists.ipxe.org/pipermail/ipxe-devel/attachments/20120716/38704d56/attachment.obj>


More information about the ipxe-devel mailing list