Jelajahi Sumber

bitbake: event/utils/methodpool: Add a cache of compiled code objects

With the addition of function line number handling, the overhead of
the compile functions is no longer negligible. We tend to compile
the same pieces of code over and over again so wrapping a cache around
this is beneficial and removes the overhead of line numbered functions.

Life cycle of a cache using a global like this is in theory problematic
although in reality unlikely to be an issue. It can be dealt with
if/as/when we deal with the other global caches.

(Bitbake rev: 98d7002d1dca4b62042e1589fd5b9b3805d57f7a)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Richard Purdie 9 tahun lalu
induk
melakukan
0381b78aa4
3 mengubah file dengan 27 tambahan dan 8 penghapusan
  1. 10 7
      bitbake/lib/bb/event.py
  2. 11 0
      bitbake/lib/bb/methodpool.py
  3. 6 1
      bitbake/lib/bb/utils.py

+ 10 - 7
bitbake/lib/bb/event.py

@@ -31,6 +31,7 @@ except ImportError:
 import logging
 import logging
 import atexit
 import atexit
 import traceback
 import traceback
+import ast
 import bb.utils
 import bb.utils
 import bb.compat
 import bb.compat
 import bb.exceptions
 import bb.exceptions
@@ -189,13 +190,15 @@ def register(name, handler, mask=None, filename=None, lineno=None):
         if isinstance(handler, basestring):
         if isinstance(handler, basestring):
             tmp = "def %s(e):\n%s" % (name, handler)
             tmp = "def %s(e):\n%s" % (name, handler)
             try:
             try:
-                import ast
-                if filename is None:
-                    filename = "%s(e)" % name
-                code = compile(tmp, filename, "exec", ast.PyCF_ONLY_AST)
-                if lineno is not None:
-                    ast.increment_lineno(code, lineno-1)
-                code = compile(code, filename, "exec")
+                code = bb.methodpool.compile_cache(tmp)
+                if not code:
+                    if filename is None:
+                        filename = "%s(e)" % name
+                    code = compile(tmp, filename, "exec", ast.PyCF_ONLY_AST)
+                    if lineno is not None:
+                        ast.increment_lineno(code, lineno-1)
+                    code = compile(code, filename, "exec")
+                    bb.methodpool.compile_cache_add(tmp, code)
             except SyntaxError:
             except SyntaxError:
                 logger.error("Unable to register event handler '%s':\n%s", name,
                 logger.error("Unable to register event handler '%s':\n%s", name,
                              ''.join(traceback.format_exc(limit=0)))
                              ''.join(traceback.format_exc(limit=0)))

+ 11 - 0
bitbake/lib/bb/methodpool.py

@@ -27,3 +27,14 @@ def insert_method(modulename, code, fn, lineno):
     comp = better_compile(code, modulename, fn, lineno=lineno)
     comp = better_compile(code, modulename, fn, lineno=lineno)
     better_exec(comp, None, code, fn)
     better_exec(comp, None, code, fn)
 
 
+compilecache = {}
+
+def compile_cache(code):
+    h = hash(code)
+    if h in compilecache:
+        return compilecache[h]
+    return None
+
+def compile_cache_add(code, compileobj):
+    h = hash(code)
+    compilecache[h] = compileobj

+ 6 - 1
bitbake/lib/bb/utils.py

@@ -298,10 +298,15 @@ def better_compile(text, file, realfile, mode = "exec", lineno = None):
     will print the offending lines.
     will print the offending lines.
     """
     """
     try:
     try:
+        cache = bb.methodpool.compile_cache(text)
+        if cache:
+            return cache
         code = compile(text, realfile, mode, ast.PyCF_ONLY_AST)
         code = compile(text, realfile, mode, ast.PyCF_ONLY_AST)
         if lineno is not None:
         if lineno is not None:
             ast.increment_lineno(code, lineno)
             ast.increment_lineno(code, lineno)
-        return compile(code, realfile, mode)
+        code = compile(code, realfile, mode)
+        bb.methodpool.compile_cache_add(text, code)
+        return code
     except Exception as e:
     except Exception as e:
         error = []
         error = []
         # split the text into lines again
         # split the text into lines again