[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