You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.2 KiB
129 lines
4.2 KiB
# Copyright 2012 Google Inc. All Rights Reserved. |
|
"""A script that symbolizes perf.data files.""" |
|
import optparse |
|
import os |
|
import shutil |
|
from subprocess import call |
|
from subprocess import PIPE |
|
from subprocess import Popen |
|
from cros_utils import misc |
|
|
|
GSUTIL_CMD = 'gsutil cp gs://chromeos-image-archive/%s-release/%s/debug.tgz %s' |
|
TAR_CMD = 'tar -zxvf %s -C %s' |
|
PERF_BINARY = '/google/data/ro/projects/perf/perf' |
|
VMLINUX_FLAG = ' --vmlinux=/usr/lib/debug/boot/vmlinux' |
|
PERF_CMD = PERF_BINARY + ' report -i %s -n --symfs=%s' + VMLINUX_FLAG |
|
|
|
|
|
def main(): |
|
parser = optparse.OptionParser() |
|
parser.add_option('--in', dest='in_dir') |
|
parser.add_option('--out', dest='out_dir') |
|
parser.add_option('--cache', dest='cache') |
|
(opts, _) = parser.parse_args() |
|
if not _ValidateOpts(opts): |
|
return 1 |
|
else: |
|
for filename in os.listdir(opts.in_dir): |
|
try: |
|
_DownloadSymbols(filename, opts.cache) |
|
_PerfReport(filename, opts.in_dir, opts.out_dir, opts.cache) |
|
except: |
|
print 'Exception caught. Continuing...' |
|
return 0 |
|
|
|
|
|
def _ValidateOpts(opts): |
|
"""Ensures all directories exist, before attempting to populate.""" |
|
if not os.path.exists(opts.in_dir): |
|
print "Input directory doesn't exist." |
|
return False |
|
if not os.path.exists(opts.out_dir): |
|
print "Output directory doesn't exist. Creating it..." |
|
os.makedirs(opts.out_dir) |
|
if not os.path.exists(opts.cache): |
|
print "Cache directory doesn't exist." |
|
return False |
|
return True |
|
|
|
|
|
def _ParseFilename(filename, canonical=False): |
|
"""Returns a tuple (key, time, board, lsb_version). |
|
If canonical is True, instead returns (database_key, board, canonical_vers) |
|
canonical_vers includes the revision string. |
|
""" |
|
key, time, board, vers = filename.split('~') |
|
if canonical: |
|
vers = misc.GetChromeOSVersionFromLSBVersion(vers) |
|
return (key, time, board, vers) |
|
|
|
|
|
def _FormReleaseDir(board, version): |
|
return '%s-release~%s' % (board, version) |
|
|
|
|
|
def _DownloadSymbols(filename, cache): |
|
""" Incrementally downloads appropriate symbols. |
|
We store the downloads in cache, with each set of symbols in a TLD |
|
named like cache/$board-release~$canonical_vers/usr/lib/debug |
|
""" |
|
_, _, board, vers = _ParseFilename(filename, canonical=True) |
|
tmp_suffix = '.tmp' |
|
|
|
tarball_subdir = _FormReleaseDir(board, vers) |
|
tarball_dir = os.path.join(cache, tarball_subdir) |
|
tarball_path = os.path.join(tarball_dir, 'debug.tgz') |
|
|
|
symbol_subdir = os.path.join('usr', 'lib') |
|
symbol_dir = os.path.join(tarball_dir, symbol_subdir) |
|
|
|
if os.path.isdir(symbol_dir): |
|
print 'Symbol directory %s exists, skipping download.' % symbol_dir |
|
return |
|
else: |
|
# First download using gsutil. |
|
if not os.path.isfile(tarball_path): |
|
download_cmd = GSUTIL_CMD % (board, vers, tarball_path + tmp_suffix) |
|
print 'Downloading symbols for %s' % filename |
|
print download_cmd |
|
ret = call(download_cmd.split()) |
|
if ret != 0: |
|
print 'gsutil returned non-zero error code: %s.' % ret |
|
# Clean up the empty directory structures. |
|
os.remove(tarball_path + tmp_suffix) |
|
raise IOError |
|
|
|
shutil.move(tarball_path + tmp_suffix, tarball_path) |
|
|
|
# Next, untar the tarball. |
|
os.makedirs(symbol_dir + tmp_suffix) |
|
extract_cmd = TAR_CMD % (tarball_path, symbol_dir + tmp_suffix) |
|
print 'Extracting symbols for %s' % filename |
|
print extract_cmd |
|
ret = call(extract_cmd.split()) |
|
if ret != 0: |
|
print 'tar returned non-zero code: %s.' % ret |
|
raise IOError |
|
shutil.move(symbol_dir + tmp_suffix, symbol_dir) |
|
os.remove(tarball_path) |
|
|
|
|
|
def _PerfReport(filename, in_dir, out_dir, cache): |
|
""" Call perf report on the file, storing output to the output dir. |
|
The output is currently stored as $out_dir/$filename |
|
""" |
|
_, _, board, vers = _ParseFilename(filename, canonical=True) |
|
symbol_cache_tld = _FormReleaseDir(board, vers) |
|
input_file = os.path.join(in_dir, filename) |
|
symfs = os.path.join(cache, symbol_cache_tld) |
|
report_cmd = PERF_CMD % (input_file, symfs) |
|
print 'Reporting.' |
|
print report_cmd |
|
report_proc = Popen(report_cmd.split(), stdout=PIPE) |
|
outfile = open(os.path.join(out_dir, filename), 'w') |
|
outfile.write(report_proc.stdout.read()) |
|
outfile.close() |
|
|
|
|
|
if __name__ == '__main__': |
|
exit(main())
|
|
|