Patch the WAF task runner to fix performance, until the issue is fixed upstream.
authorGustavo J. A. M. Carneiro <gjc@inescporto.pt>
Sat, 24 Sep 2011 13:00:29 +0100
changeset 7538 e4f691d808b1
parent 7537 375e4985e37a
child 7539 fd2a26e455b3
Patch the WAF task runner to fix performance, until the issue is fixed upstream.
wscript
wutils.py
--- a/wscript	Fri Sep 23 12:41:24 2011 +0100
+++ b/wscript	Sat Sep 24 13:00:29 2011 +0100
@@ -57,6 +57,10 @@
 
 Configure.autoconfig = 0
 
+# until http://code.google.com/p/waf/issues/detail?id=1039 gets fixed...
+wutils.monkey_patch_Runner_start()
+
+
 # the following two variables are used by the target "waf dist"
 VERSION = file("VERSION", "rt").read().strip()
 APPNAME = 'ns'
--- a/wutils.py	Fri Sep 23 12:41:24 2011 +0100
+++ b/wutils.py	Sat Sep 24 13:00:29 2011 +0100
@@ -231,3 +231,90 @@
         execvec.append("--SimulatorImplementationType=ns3::VisualSimulatorImpl")
     return run_argv([env['PYTHON'][0]] + execvec, env, cwd=cwd)
 
+
+
+def monkey_patch_Runner_start():
+    """http://code.google.com/p/waf/issues/detail?id=1039"""
+    from waflib import Task
+    def start(self):
+        """
+        Give tasks to :py:class:`waflib.Runner.TaskConsumer` instances until the build finishes or the ``stop`` flag is set.
+        If only one job is used, then execute the tasks one by one, without consumers.
+        """
+
+        self.total = self.bld.total()
+
+        while not self.stop:
+
+            self.refill_task_list()
+
+            # consider the next task
+            tsk = self.get_next_task()
+            if not tsk:
+                if self.count:
+                    # tasks may add new ones after they are run
+                    continue
+                else:
+                    # no tasks to run, no tasks running, time to exit
+                    break
+
+            if tsk.hasrun:
+                # if the task is marked as "run", just skip it
+                self.processed += 1
+                continue
+
+            if self.stop: # stop immediately after a failure was detected
+                break
+
+            try:
+                st = tsk.runnable_status()
+            except Exception:
+                self.processed += 1
+                if not self.stop and self.bld.keep:
+                    tsk.hasrun = Task.SKIPPED
+                    if self.bld.keep == 1:
+                        # if -k stop at the first exception, if -kk try to go as far as possible
+                        self.stop = True
+                    continue
+                tsk.err_msg = Utils.ex_stack()
+                tsk.hasrun = Task.EXCEPTION
+                self.error_handler(tsk)
+                continue
+
+            if st == Task.ASK_LATER:
+                self.postpone(tsk)
+                # TODO optimize this
+                # if self.outstanding:
+                #   for x in tsk.run_after:
+                #       if x in self.outstanding:
+                #           self.outstanding.remove(x)
+                #           self.outstanding.insert(0, x)
+            elif st == Task.SKIP_ME:
+                self.processed += 1
+                tsk.hasrun = Task.SKIPPED
+                self.add_more_tasks(tsk)
+            else:
+                # run me: put the task in ready queue
+                tsk.position = (self.processed, self.total)
+                self.count += 1
+                tsk.master = self
+                self.processed += 1
+
+                if self.numjobs == 1:
+                    tsk.process()
+                else:
+                    self.add_task(tsk)
+
+        # self.count represents the tasks that have been made available to the consumer threads
+        # collect all the tasks after an error else the message may be incomplete
+        while self.error and self.count:
+            self.get_out()
+
+        #print loop
+        assert (self.count == 0 or self.stop)
+
+        # free the task pool, if any
+        self.free_task_pool()
+
+    from waflib.Runner import Parallel
+    Parallel.start = start