[rkward-cvs] SF.net SVN: rkward:[3695] trunk/rkward

tfry at users.sourceforge.net tfry at users.sourceforge.net
Mon Jun 20 18:33:36 UTC 2011


Revision: 3695
          http://rkward.svn.sourceforge.net/rkward/?rev=3695&view=rev
Author:   tfry
Date:     2011-06-20 18:33:36 +0000 (Mon, 20 Jun 2011)

Log Message:
-----------
More efficient approach to output flushing in the frontend. This avoids running a timer while nothing is happening.

Modified Paths:
--------------
    trunk/rkward/ChangeLog
    trunk/rkward/rkward/rbackend/rinterface.cpp
    trunk/rkward/rkward/rbackend/rinterface.h
    trunk/rkward/rkward/rbackend/rkfrontendtransmitter.cpp
    trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.cpp
    trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.h

Modified: trunk/rkward/ChangeLog
===================================================================
--- trunk/rkward/ChangeLog	2011-06-20 18:32:25 UTC (rev 3694)
+++ trunk/rkward/ChangeLog	2011-06-20 18:33:36 UTC (rev 3695)
@@ -1,3 +1,4 @@
+- Reduce CPU usage while idle
 - Pareto-plot plugin gains more tabulation options				TODO: also use in piechart, barplot
 - rk.results() now prints rownames, where appropriate			TODO: test
 - "frame" elements in plugins can now be made checkable

Modified: trunk/rkward/rkward/rbackend/rinterface.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rinterface.cpp	2011-06-20 18:32:25 UTC (rev 3694)
+++ trunk/rkward/rkward/rbackend/rinterface.cpp	2011-06-20 18:33:36 UTC (rev 3695)
@@ -63,7 +63,7 @@
 
 #include <stdlib.h>
 
-// update output (for immediate output commands) at least this often (msecs):
+// flush new pieces of output after this period of time:
 #define FLUSH_INTERVAL 100
 
 #define GET_LIB_PATHS 1
@@ -96,13 +96,12 @@
 	backend_dead = false;
 	num_active_output_record_requests = 0;
 	previous_output_type = ROutput::NoOutput;
+	flush_timer_id = 0;
 
 	// create a fake init command
 	RCommand *fake = new RCommand (i18n ("R Startup"), RCommand::App | RCommand::Sync | RCommand::ObjectListUpdate, i18n ("R Startup"), this, STARTUP_PHASE2_COMPLETE);
 	issueCommand (fake);
 
-	startTimer (FLUSH_INTERVAL);	// calls flushOutput (false); see timerEvent ()
-
 	new RKRBackendProtocolFrontend (this);
 	RKRBackendProtocolFrontend::instance ()->setupBackend ();
 }
@@ -301,6 +300,13 @@
 void RInterface::handleRequest (RBackendRequest* request) {
 	RK_TRACE (RBACKEND);
 
+	if (request->type == RBackendRequest::OutputStartedNotification) {
+		RK_ASSERT (flush_timer_id == 0);
+		flush_timer_id = startTimer (FLUSH_INTERVAL);	// calls flushOutput (false); see timerEvent ()
+		RKRBackendProtocolFrontend::setRequestCompleted (request);
+		return;
+	}
+
 	flushOutput (true);
 	if (request->type == RBackendRequest::CommandOut) {
 		RCommandProxy *cproxy = request->takeCommand ();
@@ -351,9 +357,16 @@
 void RInterface::flushOutput (bool forced) {
 // do not trace. called periodically
 //	RK_TRACE (RBACKEND);
-
 	ROutputList list = RKRBackendProtocolFrontend::instance ()->flushOutput (forced);
 
+	// this must come _after_ the output has been flushed.
+	if (forced || !list.isEmpty ()) {
+		if (flush_timer_id != 0) {
+			killTimer (flush_timer_id);
+			flush_timer_id = 0;
+		}
+	}
+
 	foreach (ROutput *output, list) {
 		if (all_current_commands.isEmpty ()) {
 			RK_DO (qDebug ("output without receiver'%s'", qPrintable (output->output)), RBACKEND, DL_WARNING);

Modified: trunk/rkward/rkward/rbackend/rinterface.h
===================================================================
--- trunk/rkward/rkward/rbackend/rinterface.h	2011-06-20 18:32:25 UTC (rev 3694)
+++ trunk/rkward/rkward/rbackend/rinterface.h	2011-06-20 18:33:36 UTC (rev 3695)
@@ -77,6 +77,7 @@
 	static bool isNaInt (int value) { return na_int == value; };
 private:
 	void timerEvent (QTimerEvent *);
+	int flush_timer_id;
 /** Calls RThread::flushOutput(), and takes care of adding the output to all applicable commands */
 	void flushOutput (bool forced);
 /** pointer to the RThread */

Modified: trunk/rkward/rkward/rbackend/rkfrontendtransmitter.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkfrontendtransmitter.cpp	2011-06-20 18:32:25 UTC (rev 3694)
+++ trunk/rkward/rkward/rbackend/rkfrontendtransmitter.cpp	2011-06-20 18:33:36 UTC (rev 3695)
@@ -111,7 +111,12 @@
 		ROutputList* list = request->output;
 		for (int i = 0; i < list->size (); ++i) {
 			ROutput *out = (*list)[i];
-			handleOutput (out->output, out->output.length (), out->type);
+
+			if (handleOutput (out->output, out->output.length (), out->type)) {
+				RKRBackendEvent* event = new RKRBackendEvent (new RBackendRequest (false, RBackendRequest::OutputStartedNotification));
+				qApp->postEvent (RKRBackendProtocolFrontend::instance (), event);
+			}
+
 			delete (out);
 		}
 		request->output = 0;

Modified: trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.cpp	2011-06-20 18:32:25 UTC (rev 3694)
+++ trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.cpp	2011-06-20 18:33:36 UTC (rev 3695)
@@ -93,8 +93,8 @@
 	RK_TRACE (RBACKEND);
 }
 
-void RKROutputBuffer::handleOutput (const QString &output, int buf_length, ROutput::ROutputType output_type, bool allow_blocking) {
-	if (!buf_length) return;
+bool RKROutputBuffer::handleOutput (const QString &output, int buf_length, ROutput::ROutputType output_type, bool allow_blocking) {
+	if (!buf_length) return false;
 	RK_TRACE (RBACKEND);
 
 	RK_DO (qDebug ("Output type %d: %s", output_type, qPrintable (output)), RBACKEND, DL_DEBUG);
@@ -105,6 +105,7 @@
 	}
 
 	output_buffer_mutex.lock ();
+	bool previously_empty = (out_buf_len <= 0);
 
 	ROutput *current_output = 0;
 	if (!output_buffer.isEmpty ()) {
@@ -122,6 +123,7 @@
 	out_buf_len += buf_length;
 
 	output_buffer_mutex.unlock ();
+	return previously_empty;
 }
 
 ROutputList RKROutputBuffer::flushOutput (bool forcibly) {

Modified: trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.h	2011-06-20 18:32:25 UTC (rev 3694)
+++ trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.h	2011-06-20 18:33:36 UTC (rev 3695)
@@ -49,6 +49,7 @@
 		Output,		/**< A piece of output. Note: If the backend runs in a single process, output is handled in a pull fashion, instead of using requests. */
 		Interrupt,	/**< Interrupt evaluation. This request type originates in the frontend, not the backend (the only one so far). */
 #endif
+		OutputStartedNotification, /**< Only used in the frontend: Notification that a new bit of output has arrived. Used to trigger flushing after a timeout. */
 		OtherRequest		/**< Any other type of request. Note: which requests are in the enum, and which are not has mostly historical reasons. @see params */
 	};
 
@@ -133,8 +134,9 @@
 	RKROutputBuffer ();
 	virtual ~RKROutputBuffer ();
 
-/** This gets called on normal R output (R_WriteConsole). Used to get at output. */
-	void handleOutput (const QString &output, int len, ROutput::ROutputType type, bool allow_blocking=true);
+/** This gets called on normal R output (R_WriteConsole). Used to get at output.
+    returns true, if a *new* piece of output started, i.e. the buffer was empty before this. */
+	bool handleOutput (const QString &output, int len, ROutput::ROutputType type, bool allow_blocking=true);
 
 /** Flushes current output buffer. Meant to be called from RInterface::flushOutput, only.
 @param forcibly: if true, will always flush the output. If false, will flush the output only if the mutex can be locked without waiting. */


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the rkward-tracker mailing list