summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Larson <chris_larson@mentor.com>2010-11-18 22:47:36 -0700
committerRichard Purdie <rpurdie@linux.intel.com>2011-01-04 14:46:43 +0000
commit7c9444e9a58438058ec577bd8c2e51820c98072d (patch)
tree55074d2c00afa924707bb5b5d30b22bc6688594d
parent95d2f56126d459b9e7f000d22ed7c1206d1a8f68 (diff)
downloadpoky-7c9444e9a58438058ec577bd8c2e51820c98072d.tar.gz
cache: sync the cache file to disk in the background
This version uses a thread rather than a process, to avoid problems with waitpid handling. This gives slightly less overall build time reduction than the separate process for it did (this reduces a -c compile coreutils-native by about 3 seconds, while the process reduced it by 7 seconds), however this time is quite insignificant relative to a typical build. The biggest issue with non-backgrounded syncing is the perceived delay before work begins, and this resolves that without breaking anything, or so it seems. (Bitbake rev: 5ab6c5c7b007b8c77c751582141afc07c183d672) Signed-off-by: Chris Larson <chris_larson@mentor.com> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
-rw-r--r--bitbake/lib/bb/cooker.py31
-rw-r--r--bitbake/lib/bb/event.py20
-rw-r--r--bitbake/lib/bb/ui/knotty.py34
-rw-r--r--bitbake/lib/bb/ui/uievent.py18
4 files changed, 60 insertions, 43 deletions
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py
index 0143c149b8..ac9758d402 100644
--- a/bitbake/lib/bb/cooker.py
+++ b/bitbake/lib/bb/cooker.py
@@ -25,6 +25,7 @@ from __future__ import print_function
25import sys, os, glob, os.path, re, time 25import sys, os, glob, os.path, re, time
26import logging 26import logging
27import sre_constants 27import sre_constants
28import threading
28import multiprocessing 29import multiprocessing
29import signal 30import signal
30from cStringIO import StringIO 31from cStringIO import StringIO
@@ -983,6 +984,7 @@ class CookerParser(object):
983 # Internal data 984 # Internal data
984 self.filelist = filelist 985 self.filelist = filelist
985 self.cooker = cooker 986 self.cooker = cooker
987 self.cfgdata = cooker.configuration.data
986 988
987 # Accounting statistics 989 # Accounting statistics
988 self.parsed = 0 990 self.parsed = 0
@@ -1006,7 +1008,6 @@ class CookerParser(object):
1006 self.result_queue = multiprocessing.Queue() 1008 self.result_queue = multiprocessing.Queue()
1007 1009
1008 self.fromcache = [] 1010 self.fromcache = []
1009 cfgdata = self.cooker.configuration.data
1010 for filename in self.filelist: 1011 for filename in self.filelist:
1011 appends = self.cooker.get_file_appends(filename) 1012 appends = self.cooker.get_file_appends(filename)
1012 if not self.cooker.bb_cache.cacheValid(filename): 1013 if not self.cooker.bb_cache.cacheValid(filename):
@@ -1021,13 +1022,13 @@ class CookerParser(object):
1021 output.put(infos) 1022 output.put(infos)
1022 1023
1023 self.processes = [] 1024 self.processes = []
1024 num_processes = int(cfgdata.getVar("BB_NUMBER_PARSE_THREADS", True) or 1025 num_processes = int(self.cfgdata.getVar("BB_NUMBER_PARSE_THREADS", True) or
1025 multiprocessing.cpu_count()) 1026 multiprocessing.cpu_count())
1026 for i in xrange(num_processes): 1027 for i in xrange(num_processes):
1027 process = multiprocessing.Process(target=worker, 1028 process = multiprocessing.Process(target=worker,
1028 args=(self.task_queue, 1029 args=(self.task_queue,
1029 self.result_queue, 1030 self.result_queue,
1030 cfgdata)) 1031 self.cfgdata))
1031 process.start() 1032 process.start()
1032 self.processes.append(process) 1033 self.processes.append(process)
1033 1034
@@ -1041,29 +1042,29 @@ class CookerParser(object):
1041 self.task_queue.close() 1042 self.task_queue.close()
1042 for process in self.processes: 1043 for process in self.processes:
1043 process.join() 1044 process.join()
1044 self.cooker.bb_cache.sync() 1045 threading.Thread(target=self.cooker.bb_cache.sync).start()
1045 bb.codeparser.parser_cache_save(self.cooker.configuration.data) 1046 threading.Thread(target=bb.codeparser.parser_cache_save(self.cooker.configuration.data)).start()
1046 if self.error > 0: 1047 if self.error > 0:
1047 raise ParsingErrorsFound() 1048 raise ParsingErrorsFound()
1048 1049
1049 def progress(self):
1050 bb.event.fire(bb.event.ParseProgress(self.cached, self.parsed,
1051 self.skipped, self.masked,
1052 self.virtuals, self.error,
1053 self.total),
1054 self.cooker.configuration.event_data)
1055
1056 def parse_next(self): 1050 def parse_next(self):
1057 cooker = self.cooker 1051 cooker = self.cooker
1058 if self.current >= self.total: 1052 if self.current >= self.total:
1053 event = bb.event.ParseCompleted(self.cached, self.parsed,
1054 self.skipped, self.masked,
1055 self.virtuals, self.error,
1056 self.total)
1057 bb.event.fire(event, self.cfgdata)
1059 self.shutdown() 1058 self.shutdown()
1060 return False 1059 return False
1060 elif self.current == 0:
1061 bb.event.fire(bb.event.ParseStarted(self.total, self.skipped, self.masked),
1062 self.cfgdata)
1061 1063
1062 try: 1064 try:
1063 if self.result_queue.empty() and self.fromcache: 1065 if self.result_queue.empty() and self.fromcache:
1064 filename, appends = self.fromcache.pop() 1066 filename, appends = self.fromcache.pop()
1065 _, infos = cooker.bb_cache.load(filename, appends, 1067 _, infos = cooker.bb_cache.load(filename, appends, self.cfgdata)
1066 self.cooker.configuration.data)
1067 parsed = False 1068 parsed = False
1068 else: 1069 else:
1069 infos = self.result_queue.get() 1070 infos = self.result_queue.get()
@@ -1087,7 +1088,7 @@ class CookerParser(object):
1087 if info.skipped: 1088 if info.skipped:
1088 self.skipped += 1 1089 self.skipped += 1
1089 finally: 1090 finally:
1090 self.progress() 1091 bb.event.fire(bb.event.ParseProgress(self.current), self.cfgdata)
1091 1092
1092 self.current += 1 1093 self.current += 1
1093 return True 1094 return True
diff --git a/bitbake/lib/bb/event.py b/bitbake/lib/bb/event.py
index 5f292bccbc..5b0a183acd 100644
--- a/bitbake/lib/bb/event.py
+++ b/bitbake/lib/bb/event.py
@@ -296,10 +296,16 @@ class MultipleProviders(Event):
296 """ 296 """
297 return self._candidates 297 return self._candidates
298 298
299class ParseProgress(Event): 299class ParseStarted(Event):
300 """ 300 """Recipe parsing for the runqueue has begun"""
301 Parsing Progress Event 301 def __init__(self, total, skipped, masked):
302 """ 302 Event.__init__(self)
303 self.total = total
304 self.skipped = skipped
305 self.masked = masked
306
307class ParseCompleted(Event):
308 """Recipe parsing for the runqueue has completed"""
303 309
304 def __init__(self, cached, parsed, skipped, masked, virtuals, errors, total): 310 def __init__(self, cached, parsed, skipped, masked, virtuals, errors, total):
305 Event.__init__(self) 311 Event.__init__(self)
@@ -312,6 +318,12 @@ class ParseProgress(Event):
312 self.sofar = cached + parsed 318 self.sofar = cached + parsed
313 self.total = total 319 self.total = total
314 320
321class ParseProgress(Event):
322 """Recipe parsing progress"""
323
324 def __init__(self, current):
325 self.current = current
326
315class DepTreeGenerated(Event): 327class DepTreeGenerated(Event):
316 """ 328 """
317 Event when a dependency tree has been generated 329 Event when a dependency tree has been generated
diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py
index a34991bb68..326f164353 100644
--- a/bitbake/lib/bb/ui/knotty.py
+++ b/bitbake/lib/bb/ui/knotty.py
@@ -78,6 +78,7 @@ def init(server, eventHandler):
78 return 1 78 return 1
79 79
80 pbar = None 80 pbar = None
81 interactive = os.isatty(sys.stdout.fileno())
81 shutdown = 0 82 shutdown = 0
82 return_value = 0 83 return_value = 0
83 while True: 84 while True:
@@ -132,23 +133,26 @@ def init(server, eventHandler):
132 if isinstance(event, bb.build.TaskBase): 133 if isinstance(event, bb.build.TaskBase):
133 logger.info(event._message) 134 logger.info(event._message)
134 continue 135 continue
136 if isinstance(event, bb.event.ParseStarted):
137 if interactive:
138 pbar = progressbar.ProgressBar(widgets=widgets,
139 maxval=event.total).start()
140 else:
141 sys.stdout.write("Parsing recipes...")
142 sys.stdout.flush()
143 continue
135 if isinstance(event, bb.event.ParseProgress): 144 if isinstance(event, bb.event.ParseProgress):
136 current, total = event.sofar, event.total 145 if interactive:
137 if os.isatty(sys.stdout.fileno()): 146 pbar.update(event.current)
138 if not pbar: 147 continue
139 pbar = progressbar.ProgressBar(widgets=widgets, 148 if isinstance(event, bb.event.ParseCompleted):
140 maxval=total).start() 149 if interactive:
141 pbar.update(current) 150 pbar.update(event.total)
142 else: 151 else:
143 if current == 1: 152 sys.stdout.write("done.\n")
144 sys.stdout.write("Parsing .bb files, please wait...") 153 sys.stdout.flush()
145 sys.stdout.flush() 154 print(("\nParsing of %d .bb files complete (%d cached, %d parsed). %d targets, %d skipped, %d masked, %d errors."
146 if current == total: 155 % ( event.total, event.cached, event.parsed, event.virtuals, event.skipped, event.masked, event.errors)))
147 sys.stdout.write("done.")
148 sys.stdout.flush()
149 if current == total:
150 print(("\nParsing of %d .bb files complete (%d cached, %d parsed). %d targets, %d skipped, %d masked, %d errors."
151 % ( event.total, event.cached, event.parsed, event.virtuals, event.skipped, event.masked, event.errors)))
152 continue 156 continue
153 157
154 if isinstance(event, bb.command.CookerCommandCompleted): 158 if isinstance(event, bb.command.CookerCommandCompleted):
diff --git a/bitbake/lib/bb/ui/uievent.py b/bitbake/lib/bb/ui/uievent.py
index f1e4d791ee..b404805d81 100644
--- a/bitbake/lib/bb/ui/uievent.py
+++ b/bitbake/lib/bb/ui/uievent.py
@@ -37,8 +37,8 @@ class BBUIEventQueue:
37 self.BBServer = BBServer 37 self.BBServer = BBServer
38 38
39 self.t = threading.Thread() 39 self.t = threading.Thread()
40 self.t.setDaemon(True) 40 self.t.setDaemon(True)
41 self.t.run = self.startCallbackHandler 41 self.t.run = self.startCallbackHandler
42 self.t.start() 42 self.t.start()
43 43
44 def getEvent(self): 44 def getEvent(self):
@@ -70,7 +70,7 @@ class BBUIEventQueue:
70 def startCallbackHandler(self): 70 def startCallbackHandler(self):
71 71
72 server = UIXMLRPCServer() 72 server = UIXMLRPCServer()
73 self.host, self.port = server.socket.getsockname() 73 self.host, self.port = server.socket.getsockname()
74 74
75 server.register_function( self.system_quit, "event.quit" ) 75 server.register_function( self.system_quit, "event.quit" )
76 server.register_function( self.queue_event, "event.send" ) 76 server.register_function( self.queue_event, "event.send" )
@@ -83,7 +83,7 @@ class BBUIEventQueue:
83 server.handle_request() 83 server.handle_request()
84 server.server_close() 84 server.server_close()
85 85
86 def system_quit( self ): 86 def system_quit( self ):
87 """ 87 """
88 Shut down the callback thread 88 Shut down the callback thread
89 """ 89 """
@@ -95,11 +95,11 @@ class BBUIEventQueue:
95 95
96class UIXMLRPCServer (SimpleXMLRPCServer): 96class UIXMLRPCServer (SimpleXMLRPCServer):
97 97
98 def __init__( self, interface = ("localhost", 0) ): 98 def __init__( self, interface = ("localhost", 0) ):
99 self.quit = False 99 self.quit = False
100 SimpleXMLRPCServer.__init__( self, 100 SimpleXMLRPCServer.__init__( self,
101 interface, 101 interface,
102 requestHandler=SimpleXMLRPCRequestHandler, 102 requestHandler=SimpleXMLRPCRequestHandler,
103 logRequests=False, allow_none=True) 103 logRequests=False, allow_none=True)
104 104
105 def get_request(self): 105 def get_request(self):
@@ -121,4 +121,4 @@ class UIXMLRPCServer (SimpleXMLRPCServer):
121 if request is None: 121 if request is None:
122 return 122 return
123 SimpleXMLRPCServer.process_request(self, request, client_address) 123 SimpleXMLRPCServer.process_request(self, request, client_address)
124 124