summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2015-12-20 13:22:19 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-12-22 00:01:57 +0000
commit98d7002d1dca4b62042e1589fd5b9b3805d57f7a (patch)
tree0d40f2935632917c47251a993194e9ffa02f38f6 /lib
parente0f05871c2a6f1e86ae19ad343c7c6f822ddb67e (diff)
downloadbitbake-98d7002d1dca4b62042e1589fd5b9b3805d57f7a.tar.gz
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. Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/bb/event.py17
-rw-r--r--lib/bb/methodpool.py11
-rw-r--r--lib/bb/utils.py7
3 files changed, 27 insertions, 8 deletions
diff --git a/lib/bb/event.py b/lib/bb/event.py
index bd2b0a4b0..5ffe89eae 100644
--- a/lib/bb/event.py
+++ b/lib/bb/event.py
@@ -31,6 +31,7 @@ except ImportError:
import logging
import atexit
import traceback
+import ast
import bb.utils
import bb.compat
import bb.exceptions
@@ -189,13 +190,15 @@ def register(name, handler, mask=None, filename=None, lineno=None):
if isinstance(handler, basestring):
tmp = "def %s(e):\n%s" % (name, handler)
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:
logger.error("Unable to register event handler '%s':\n%s", name,
''.join(traceback.format_exc(limit=0)))
diff --git a/lib/bb/methodpool.py b/lib/bb/methodpool.py
index b2ea1a188..49aed3338 100644
--- a/lib/bb/methodpool.py
+++ b/lib/bb/methodpool.py
@@ -27,3 +27,14 @@ def insert_method(modulename, code, fn, lineno):
comp = better_compile(code, modulename, fn, lineno=lineno)
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
diff --git a/lib/bb/utils.py b/lib/bb/utils.py
index e564bb6ff..cd5fcede3 100644
--- a/lib/bb/utils.py
+++ b/lib/bb/utils.py
@@ -298,10 +298,15 @@ def better_compile(text, file, realfile, mode = "exec", lineno = None):
will print the offending lines.
"""
try:
+ cache = bb.methodpool.compile_cache(text)
+ if cache:
+ return cache
code = compile(text, realfile, mode, ast.PyCF_ONLY_AST)
if lineno is not None:
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:
error = []
# split the text into lines again