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

Side by Side Diff: tools/binary_size/libsupersize/nm.py

Issue 2858793002: Create a star symbol for gaps at the start & end of sections (Closed)
Patch Set: Created 3 years, 7 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 unified diff | Download patch
OLDNEW
1 # Copyright 2017 The Chromium Authors. All rights reserved. 1 # Copyright 2017 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Functions that rely on parsing output of "nm" tool.""" 5 """Functions that rely on parsing output of "nm" tool."""
6 6
7 import atexit
7 import collections 8 import collections
9 import errno
8 import logging 10 import logging
9 import os 11 import os
10 import subprocess 12 import subprocess
11 import sys 13 import sys
12 14
13 import concurrent 15 import concurrent
14 16
17 _active_subprocesses = None
18
15 19
16 def CollectAliasesByAddress(elf_path, tool_prefix): 20 def CollectAliasesByAddress(elf_path, tool_prefix):
17 """Runs nm on |elf_path| and returns a dict of address->[names]""" 21 """Runs nm on |elf_path| and returns a dict of address->[names]"""
18 names_by_address = collections.defaultdict(list) 22 names_by_address = collections.defaultdict(list)
19 23
20 # About 60mb of output, but piping takes ~30s, and loading it into RAM 24 # About 60mb of output, but piping takes ~30s, and loading it into RAM
21 # directly takes 3s. 25 # directly takes 3s.
22 args = [tool_prefix + 'nm', '--no-sort', '--defined-only', '--demangle', 26 args = [tool_prefix + 'nm', '--no-sort', '--defined-only', '--demangle',
23 elf_path] 27 elf_path]
24 output = subprocess.check_output(args) 28 output = subprocess.check_output(args)
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 # It would speed up mashalling of the values by removing all entries 165 # It would speed up mashalling of the values by removing all entries
162 # that have only 1 path. However, these entries are needed to give 166 # that have only 1 path. However, these entries are needed to give
163 # path information to symbol aliases. 167 # path information to symbol aliases.
164 self._result = paths_by_name 168 self._result = paths_by_name
165 169
166 def Get(self): 170 def Get(self):
167 assert self._result is not None 171 assert self._result is not None
168 return self._result 172 return self._result
169 173
170 174
175 def _TerminateSubprocesses():
176 for proc in _active_subprocesses:
177 proc.kill()
178
179
171 class _BulkObjectFileAnalyzerMaster(object): 180 class _BulkObjectFileAnalyzerMaster(object):
172 """Runs BulkObjectFileAnalyzer in a subprocess.""" 181 """Runs BulkObjectFileAnalyzer in a subprocess."""
173 182
174 def __init__(self, tool_prefix, output_directory): 183 def __init__(self, tool_prefix, output_directory):
175 self._process = None 184 self._process = None
176 self._tool_prefix = tool_prefix 185 self._tool_prefix = tool_prefix
177 self._output_directory = output_directory 186 self._output_directory = output_directory
178 187
179 def _Spawn(self): 188 def _Spawn(self):
189 global _active_subprocesses
180 log_level = str(logging.getLogger().getEffectiveLevel()) 190 log_level = str(logging.getLogger().getEffectiveLevel())
181 args = [sys.executable, __file__, log_level, self._tool_prefix, 191 args = [sys.executable, __file__, log_level, self._tool_prefix,
182 self._output_directory] 192 self._output_directory]
183 self._process = subprocess.Popen( 193 self._process = subprocess.Popen(
184 args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) 194 args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
195 if _active_subprocesses is None:
196 _active_subprocesses = []
197 atexit.register(_TerminateSubprocesses)
198 _active_subprocesses.append(self._process)
185 199
186 def AnalyzePaths(self, paths): 200 def AnalyzePaths(self, paths):
187 if self._process is None: 201 if self._process is None:
188 self._Spawn() 202 self._Spawn()
189 203
190 logging.debug('Sending batch of %d paths to subprocess', len(paths)) 204 logging.debug('Sending batch of %d paths to subprocess', len(paths))
191 payload = '\x01'.join(paths) 205 payload = '\x01'.join(paths)
192 self._process.stdin.write('{:08x}'.format(len(payload))) 206 self._process.stdin.write('{:08x}'.format(len(payload)))
193 self._process.stdin.write(payload) 207 self._process.stdin.write(payload)
194 208
195 def Close(self): 209 def Close(self):
196 assert not self._process.stdin.closed 210 assert not self._process.stdin.closed
197 self._process.stdin.close() 211 self._process.stdin.close()
212 _active_subprocesses.remove(self._process)
198 213
199 def Get(self): 214 def Get(self):
200 assert self._process.stdin.closed 215 assert self._process.stdin.closed
201 logging.debug('Decoding nm results from forked process') 216 logging.debug('Decoding nm results from forked process')
202 217
203 encoded_keys_len = int(self._process.stdout.read(8), 16) 218 encoded_keys_len = int(self._process.stdout.read(8), 16)
204 encoded_keys = self._process.stdout.read(encoded_keys_len) 219 encoded_keys = self._process.stdout.read(encoded_keys_len)
205 encoded_values = self._process.stdout.read() 220 encoded_values = self._process.stdout.read()
206 return concurrent.DecodeDictOfLists(encoded_keys, encoded_values) 221 return concurrent.DecodeDictOfLists(encoded_keys, encoded_values)
207 222
208 223
209 BulkObjectFileAnalyzer = _BulkObjectFileAnalyzerMaster 224 BulkObjectFileAnalyzer = _BulkObjectFileAnalyzerMaster
210 if concurrent.DISABLE_ASYNC: 225 if concurrent.DISABLE_ASYNC:
211 BulkObjectFileAnalyzer = _BulkObjectFileAnalyzerWorker 226 BulkObjectFileAnalyzer = _BulkObjectFileAnalyzerWorker
212 227
213 228
214 def _SubMain(log_level, tool_prefix, output_directory): 229 def _SubMain(log_level, tool_prefix, output_directory):
215 logging.basicConfig(level=int(log_level), 230 logging.basicConfig(
216 format='%(levelname).1s %(relativeCreated)6d %(message)s') 231 level=int(log_level),
232 format='nm: %(levelname).1s %(relativeCreated)6d %(message)s')
217 bulk_analyzer = _BulkObjectFileAnalyzerWorker(tool_prefix, output_directory) 233 bulk_analyzer = _BulkObjectFileAnalyzerWorker(tool_prefix, output_directory)
218 while True: 234 while True:
219 payload_len = int(sys.stdin.read(8) or '0', 16) 235 payload_len = int(sys.stdin.read(8) or '0', 16)
220 if not payload_len: 236 if not payload_len:
221 logging.debug('nm bulk subprocess received eof.') 237 logging.debug('nm bulk subprocess received eof.')
222 break 238 break
223 paths = sys.stdin.read(payload_len).split('\x01') 239 paths = sys.stdin.read(payload_len).split('\x01')
224 bulk_analyzer.AnalyzePaths(paths) 240 bulk_analyzer.AnalyzePaths(paths)
225 241
226 bulk_analyzer.Close() 242 bulk_analyzer.Close()
227 paths_by_name = bulk_analyzer.Get() 243 paths_by_name = bulk_analyzer.Get()
228 encoded_keys, encoded_values = concurrent.EncodeDictOfLists(paths_by_name) 244 encoded_keys, encoded_values = concurrent.EncodeDictOfLists(paths_by_name)
229 sys.stdout.write('%08x' % len(encoded_keys)) 245 try:
230 sys.stdout.write(encoded_keys) 246 sys.stdout.write('%08x' % len(encoded_keys))
231 sys.stdout.write(encoded_values) 247 sys.stdout.write(encoded_keys)
248 sys.stdout.write(encoded_values)
249 except IOError, e:
250 # Parent process exited.
251 if e.errno == errno.EPIPE:
252 sys.exit(1)
253
232 logging.debug('nm bulk subprocess finished.') 254 logging.debug('nm bulk subprocess finished.')
233 255
234 256
235 if __name__ == '__main__': 257 if __name__ == '__main__':
236 _SubMain(*sys.argv[1:]) 258 _SubMain(*sys.argv[1:])
OLDNEW
« no previous file with comments | « tools/binary_size/libsupersize/models.py ('k') | tools/binary_size/libsupersize/testdata/Archive.golden » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698