• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2015 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4import json
5import os
6import re
7import sys
8import tempfile
9import types
10
11import perf_insights_project
12import vinn
13
14from perf_insights.mre import failure
15from perf_insights.mre import mre_result
16
17_MAP_SINGLE_TRACE_CMDLINE_PATH = os.path.join(
18    perf_insights_project.PerfInsightsProject.perf_insights_src_path,
19    'map_single_trace_cmdline.html')
20
21class TemporaryMapScript(object):
22  def __init__(self, js):
23    temp_file = tempfile.NamedTemporaryFile(delete=False)
24    temp_file.write("""
25<!DOCTYPE html>
26<script>
27%s
28</script>
29""" % js)
30    temp_file.close()
31    self._filename = temp_file.name
32
33  def __enter__(self):
34    return self
35
36  def __exit__(self, *args, **kwargs):
37    os.remove(self._filename)
38    self._filename = None
39
40  @property
41  def filename(self):
42    return self._filename
43
44
45class FunctionLoadingFailure(failure.Failure):
46  pass
47
48class FunctionNotDefinedFailure(failure.Failure):
49  pass
50
51class MapFunctionFailure(failure.Failure):
52  pass
53
54class FileLoadingFailure(failure.Failure):
55  pass
56
57class TraceImportFailure(failure.Failure):
58  pass
59
60class NoResultsAddedFailure(failure.Failure):
61  pass
62
63class InternalMapError(Exception):
64  pass
65
66_FAILURE_NAME_TO_FAILURE_CONSTRUCTOR = {
67  'FileLoadingError': FileLoadingFailure,
68  'FunctionLoadingError': FunctionLoadingFailure,
69  'FunctionNotDefinedError': FunctionNotDefinedFailure,
70  'TraceImportError': TraceImportFailure,
71  'MapFunctionError': MapFunctionFailure,
72  'NoResultsAddedError': NoResultsAddedFailure
73}
74
75
76def MapSingleTrace(trace_handle,
77                   job,
78                   extra_import_options=None):
79  assert (type(extra_import_options) is types.NoneType or
80          type(extra_import_options) is types.DictType), (
81         'extra_import_options should be a dict or None.')
82  project = perf_insights_project.PerfInsightsProject()
83
84  all_source_paths = list(project.source_paths)
85  all_source_paths.append(project.perf_insights_root_path)
86
87  result = mre_result.MreResult()
88
89  with trace_handle.PrepareFileForProcessing() as prepared_trace_handle:
90    js_args = [
91      json.dumps(prepared_trace_handle.AsDict()),
92      json.dumps(job.AsDict()),
93    ]
94    if extra_import_options:
95      js_args.append(json.dumps(extra_import_options))
96
97    res = vinn.RunFile(
98      _MAP_SINGLE_TRACE_CMDLINE_PATH, source_paths=all_source_paths,
99      js_args=js_args)
100
101  if res.returncode != 0:
102    try:
103      sys.stderr.write(res.stdout)
104    except Exception:
105      pass
106    result.AddFailure(failure.Failure(
107        job.map_function_handle.AsUserFriendlyString(),
108        trace_handle.canonical_url,
109        'Error', 'vinn runtime error while mapping trace.',
110        'vinn runtime error while mapping trace.', 'Unknown stack'))
111    return result
112
113  for line in res.stdout.split('\n'):
114    m = re.match('^MRE_RESULT: (.+)', line, re.DOTALL)
115    if m:
116      found_dict = json.loads(m.group(1))
117      failures = [failure.Failure.FromDict(
118                    f, job, _FAILURE_NAME_TO_FAILURE_CONSTRUCTOR)
119                  for f in found_dict['failures']]
120
121      for f in failures:
122        result.AddFailure(f)
123
124      for k, v in found_dict['pairs'].iteritems():
125        result.AddPair(k, v)
126
127    else:
128      if len(line) > 0:
129        sys.stderr.write(line)
130        sys.stderr.write('\n')
131
132  if not (len(result.pairs) or len(result.failures)):
133    raise InternalMapError('Internal error: No results were produced!')
134
135  return result
136