Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(503)

Unified Diff: build/android/pylib/symbols/elf_symbolizer.py

Issue 311443002: elf_symbolizer: Use a process for max 4000 lookups and then restart (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: addr2line count limit Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: build/android/pylib/symbols/elf_symbolizer.py
diff --git a/build/android/pylib/symbols/elf_symbolizer.py b/build/android/pylib/symbols/elf_symbolizer.py
index 90e99e5a2757770b30d8d3a89d0a34b589212780..b294654f20b1ee3c7f0cdb5c142789f3bc1b5933 100644
--- a/build/android/pylib/symbols/elf_symbolizer.py
+++ b/build/android/pylib/symbols/elf_symbolizer.py
@@ -15,6 +15,13 @@ import sys
import threading
+# addr2line builds a possibly infinite memory cache that can exhaust
+# the computer's memory if allowed to grow for too long. This constant
+# controls how many lookups we do before restarting the process. 4000
+# gives near peak performance without extreme memory usage.
+ADDR2LINE_RECYCLE_LIMIT = 4000
+
+
class ELFSymbolizer(object):
"""An uber-fast (multiprocessing, pipelined and asynchronous) ELF symbolizer.
@@ -117,6 +124,7 @@ class ELFSymbolizer(object):
# Essentially, this drains all the addr2line(s) out queues.
for a2l_to_purge in self._a2l_instances:
a2l_to_purge.ProcessAllResolvedSymbolsInQueue()
+ a2l_to_purge.RecycleIfNecessary()
# Find the best instance according to this logic:
# 1. Find an existing instance with the shortest queue.
@@ -184,6 +192,10 @@ class ELFSymbolizer(object):
# separate field because turned out to be a perf hot-spot.
self.queue_size = 0
+ # Keep track of the number of symbols a process has processed to
+ # avoid a single process growing too big and using all the memory.
+ self._processed_symbols_count = 0
+
# Objects required to handle the addr2line subprocess.
self._proc = None # Subprocess.Popen(...) instance.
self._thread = None # Threading.thread instance.
@@ -251,6 +263,15 @@ class ELFSymbolizer(object):
break
self._ProcessSymbolOutput(lines)
+ def RecycleIfNecessary(self):
+ """Restarts the process if it has been used for too long.
+
+ A long running addr2line process will consume excessive amounts
+ of memory without any gain in performance."""
+ if self._processed_symbols_count >= ADDR2LINE_RECYCLE_LIMIT:
+ self._RestartAddr2LineProcess()
+
+
def Terminate(self):
"""Kills the underlying addr2line process.
@@ -297,6 +318,7 @@ class ELFSymbolizer(object):
if not innermost_sym_info:
innermost_sym_info = sym_info
+ self._processed_symbols_count += 1
self._symbolizer.callback(innermost_sym_info, callback_arg)
def _RestartAddr2LineProcess(self):
@@ -325,6 +347,8 @@ class ELFSymbolizer(object):
self._thread.daemon = True # Don't prevent early process exit.
self._thread.start()
+ self._processed_symbols_count = 0
+
# Replay the pending requests on the new process (only for the case
# of a hung addr2line timing out during the game).
for (addr, _, _) in self._request_queue:
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698