diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-07-24 11:40:55 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-07-24 23:28:35 +0100 |
commit | 9901415ecd11df0da73fccd867c4f1ba39abc9ab (patch) | |
tree | 1032349b26f2d3b83722620759be461150f4b3ea | |
parent | 67c6cc854f0add255a0559b9104c83b5d2ffde64 (diff) | |
download | poky-9901415ecd11df0da73fccd867c4f1ba39abc9ab.tar.gz |
bitbake: data_smart: Improve performance of infer_caller_details()
As things stand now, bitbake -e (which turns on all the caller tracking)
of OE-Core generates around 9.5 million stat calls which is slow and the
largest single thing on the profile data.
This is because infer_caller_details() calls traceback.extract_stack()
which adds line contents to the traceback. This in turn calls python's
internal linecache code which calls stat on every file for every callback.
We don't even use that info. We only even want a single frame of the stack.
Instead, open code for the pieces of information we need. Also, only
obtain the stack once for both halves of the infer_caller_details()
code.
This reduces the number of stat calls to around 0.5 million and significantly
improves parsing with bitbake -e.
(Bitbake rev: 7be76d8f79ea92fd4bd36146eb9a4b86551b526d)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | bitbake/lib/bb/data_smart.py | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/bitbake/lib/bb/data_smart.py b/bitbake/lib/bb/data_smart.py index a7cae77d36..f0187b7a17 100644 --- a/bitbake/lib/bb/data_smart.py +++ b/bitbake/lib/bb/data_smart.py | |||
@@ -54,27 +54,36 @@ def infer_caller_details(loginfo, parent = False, varval = True): | |||
54 | return | 54 | return |
55 | # Infer caller's likely values for variable (var) and value (value), | 55 | # Infer caller's likely values for variable (var) and value (value), |
56 | # to reduce clutter in the rest of the code. | 56 | # to reduce clutter in the rest of the code. |
57 | if varval and ('variable' not in loginfo or 'detail' not in loginfo): | 57 | above = None |
58 | def set_above(): | ||
58 | try: | 59 | try: |
59 | raise Exception | 60 | raise Exception |
60 | except Exception: | 61 | except Exception: |
61 | tb = sys.exc_info()[2] | 62 | tb = sys.exc_info()[2] |
62 | if parent: | 63 | if parent: |
63 | above = tb.tb_frame.f_back.f_back | 64 | return tb.tb_frame.f_back.f_back.f_back |
64 | else: | 65 | else: |
65 | above = tb.tb_frame.f_back | 66 | return tb.tb_frame.f_back.f_back |
66 | lcls = above.f_locals.items() | 67 | |
68 | if varval and ('variable' not in loginfo or 'detail' not in loginfo): | ||
69 | if not above: | ||
70 | above = set_above() | ||
71 | lcls = above.f_locals.items() | ||
67 | for k, v in lcls: | 72 | for k, v in lcls: |
68 | if k == 'value' and 'detail' not in loginfo: | 73 | if k == 'value' and 'detail' not in loginfo: |
69 | loginfo['detail'] = v | 74 | loginfo['detail'] = v |
70 | if k == 'var' and 'variable' not in loginfo: | 75 | if k == 'var' and 'variable' not in loginfo: |
71 | loginfo['variable'] = v | 76 | loginfo['variable'] = v |
72 | # Infer file/line/function from traceback | 77 | # Infer file/line/function from traceback |
78 | # Don't use traceback.extract_stack() since it fills the line contents which | ||
79 | # we don't need and that hits stat syscalls | ||
73 | if 'file' not in loginfo: | 80 | if 'file' not in loginfo: |
74 | depth = 3 | 81 | if not above: |
75 | if parent: | 82 | above = set_above() |
76 | depth = 4 | 83 | f = above.f_back |
77 | file, line, func, text = traceback.extract_stack(limit = depth)[0] | 84 | line = f.f_lineno |
85 | file = f.f_code.co_filename | ||
86 | func = f.f_code.co_name | ||
78 | loginfo['file'] = file | 87 | loginfo['file'] = file |
79 | loginfo['line'] = line | 88 | loginfo['line'] = line |
80 | if func not in loginfo: | 89 | if func not in loginfo: |