Commit 367711e9 authored by Changwan Ryu's avatar Changwan Ryu Committed by Commit Bot

Speed up simpleperf address matching

Currently, it takes 120 seconds for 2,000 Hz sampling,
and it takes more than 5 minutes for 10,000 Hz sampling.

This is slow because of the use of double loops. This can be avoided by
using a hashmap (dict) and a single loop with a more lenient pattern
matching. (ntfschr@'s idea)

With this change, the address matching part takes < 1 second.

Also, this adds some more logging to understand what is going on, and
adds a test case around the address that was not recognized.

Test: run_simpleperf_test covers this
Test: output result looks correct.
Bug: 1048428
Change-Id: I795c83133baeb07f8b78342d94e6d3b227eebd61
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2063811
Commit-Queue: Changwan Ryu <changwan@chromium.org>
Reviewed-by: default avatarNate Fischer <ntfschr@chromium.org>
Reviewed-by: default avatarOksana Zhuravlova <oksamyt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#743196}
parent d1431dc0
......@@ -98,6 +98,9 @@ class StackAddressInterpreter(object):
for i in range(max(10, len(stack_output))):
logging.debug(stack_output[i])
logging.info('We got the results from the stack script. Translating the '
'addresses...')
address_function_pairs = []
pattern = re.compile(r' 0*(?P<address>[1-9a-f][0-9a-f]+) (?P<function>.*)'
r' (?P<file_name_line>.*)')
......@@ -109,6 +112,8 @@ class StackAddressInterpreter(object):
function_info += " | " + m.group('file_name_line')
address_function_pairs.append((m.group('address'), function_info))
logging.info('The translation is done.')
return address_function_pairs
......@@ -164,6 +169,7 @@ class SimplePerfRunner(object):
logging.info("Extracted %d addresses", len(addresses))
address_function_pairs = self.address_interpreter.Interpret(
addresses, lib_path)
lines = SimplePerfRunner.ReplaceAddressesWithFunctionInfos(
lines, address_function_pairs, lib_name)
......@@ -254,14 +260,31 @@ class SimplePerfRunner(object):
A list of strings with addresses replaced by function names.
"""
address_count = 0
for address, function in address_function_pairs:
pattern = re.compile(lib_name + r'\[\+' + address + r'\]')
for i, line in enumerate(lines):
address_count += len(pattern.findall(line))
lines[i] = pattern.sub(
lib_name + '[' + cgi.escape(function) + ']', line)
logging.info('There were %d matching addresses', address_count)
logging.info('Replacing the HTML content with new function names...')
# Note: Using a lenient pattern matching and a hashmap (dict) is much faster
# than using a double loop (by the order of 1,000).
# '+address' will be replaced by function name.
address_function_dict = {
'+' + k: cgi.escape(v)
for k, v in address_function_pairs
}
# Look behind the lib_name and '[' which will not be substituted. Note that
# '+' is used in the pattern but will be removed.
pattern = re.compile(r'(?<=' + lib_name + r'\[)\+([a-f0-9]+)(?=\])')
def replace_fn(match):
address = match.group(0)
if address in address_function_dict:
return address_function_dict[address]
else:
return address
# Line-by-line assignment to avoid creating a temp list.
for i, line in enumerate(lines):
lines[i] = pattern.sub(replace_fn, line)
logging.info('Replacing is done.')
return lines
......
......@@ -70,9 +70,11 @@ _EXAMPLE_INTERPRETER_OUTPUT_WITH_FILE_NAME_LINE = [
_MOCK_ORIGINAL_REPORT = [
'"442": {"l": 28, "f": "libwebviewchromium.so[+3db7d84]"},',
'"443": {"l": 28, "f": "libwebviewchromium.so[+3db7a5c]"},']
'"443": {"l": 28, "f": "libwebviewchromium.so[+3db7a5c]"},',
'"444": {"l": 28, "f": "libwebviewchromium.so[+aaaaaaa]"},'
]
_MOCK_ADDRESSES = ['3db7d84', '3db7a5c']
_MOCK_ADDRESSES = ['3db7d84', '3db7a5c', 'aaaaaaa']
_MOCK_ADDRESS_FUNCTION_NAME_PAIRS = [
('3db7d84', 'MyClass::FirstMethod(const char*)'),
......@@ -82,7 +84,9 @@ _MOCK_FINAL_REPORT = [
('"442": {"l": 28, "f": "libwebviewchromium.so[MyClass::'
'FirstMethod(const char*)]"},'),
('"443": {"l": 28, "f": "libwebviewchromium.so[MyClass::'
'SecondMethod(int)]"},')]
'SecondMethod(int)]"},'),
('"444": {"l": 28, "f": "libwebviewchromium.so[+aaaaaaa]"},')
]
class _RunSimpleperfTest(unittest.TestCase):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment