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

Side by Side Diff: chrome/test/vr/perf/latency/webvr_latency_test.py

Issue 2823883003: Make VR latency results compatible with perf dashboard, refactor into classes (Closed)
Patch Set: windows -> win Created 3 years, 8 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
(Empty)
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
3 # found in the LICENSE file.
4
5 import motopho_thread as mt
6 import robot_arm as ra
7
8 import json
9 import glob
10 import logging
11 import os
12 import re
13 import subprocess
14 import sys
15 import time
16
17 MOTOPHO_THREAD_TIMEOUT = 30
18
19 def GetTtyDevices(tty_pattern, vendor_ids):
20 """Find all devices connected to tty that match a pattern and device id.
Lei Lei 2017/04/17 22:57:13 s/Find/Finds
bsheedy 2017/04/18 21:17:26 Done.
21
22 If a serial device is connected to the computer via USB, this function
23 will check all tty devices that match tty_pattern, and return the ones
24 that have vendor identification number in the list vendor_ids.
25
26 Args:
27 tty_pattern: The search pattern, such as r'ttyACM\d+'.
28 vendor_ids: The list of 16-bit USB vendor ids, such as [0x2a03].
29
30 Returns:
31 A list of strings of tty devices, for example ['ttyACM0'].
32 """
33 product_string = 'PRODUCT='
34 sys_class_dir = '/sys/class/tty/'
35
36 tty_devices = glob.glob(sys_class_dir + '*')
37
38 matcher = re.compile('.*' + tty_pattern)
39 tty_matches = [x for x in tty_devices if matcher.search(x)]
40 tty_matches = [x[len(sys_class_dir):] for x in tty_matches]
41
42 found_devices = []
43 for match in tty_matches:
44 class_filename = sys_class_dir + match + '/device/uevent'
45 with open(class_filename, 'r') as uevent_file:
46 # Look for the desired product id in the uevent text.
47 for line in uevent_file:
48 if product_string in line:
49 ids = line[len(product_string):].split('/')
50 ids = [int(x, 16) for x in ids]
51
52 for desired_id in vendor_ids:
53 if desired_id in ids:
54 found_devices.append(match)
55
56 return found_devices
57
58 class WebVrLatencyTest(object):
59 """Base class for all WebVR latency tests.
60
61 This is meant to be subclassed for each platform the test is run on. While
62 the latency test itself is cross-platform, the setup and teardown for
63 tests is platform-dependent.
64 """
65 def __init__(self, args):
66 self.args = args
67 self.device_name = 'generic_device'
68 # Connect to the Arduino that drives the servos
69 devices = GetTtyDevices(r'ttyACM\d+', [0x2a03, 0x2341])
70 assert (len(devices) == 1),'Found %d devices, expected 1' % len(devices)
71 self.robot_arm = ra.RobotArm(devices[0])
72
73 def RunTest(self):
74 """Runs the steps to start Chrome, measure/save latency, and clean up."""
75 self._Setup()
76 self._Run()
77 self._Teardown()
78
79 def _Setup(self):
80 """Perform any platform-specific setup."""
81 raise NotImplementedError(
82 'Platform-specific setup must be implemented in subclass')
83
84 def _Run(self):
85 """Run the latency test.
86
87 Handles the actual latency measurement, which is identical across
88 different platforms, as well as result saving.
89 """
90 # Motopho scripts use relative paths, so switch to the Motopho directory
91 os.chdir(self.args.motopho_path)
92 # Start the Motopho script
93 motopho_thread = mt.MotophoThread()
94 motopho_thread.start()
95 # Let the Motopho be stationary so the script can calculate the bias
96 time.sleep(3)
97 # Move so we can measure latency
98 self.robot_arm.StartMotophoMovement()
99 motopho_thread.join(MOTOPHO_THREAD_TIMEOUT)
100 if motopho_thread.isAlive():
101 # TODO(bsheedy): Look into ways to prevent Motopho from not sending any
102 # data until unplugged and replugged into the machine after a reboot.
103 logging.error('Motopho thread timeout, Motopho may need to be replugged.')
104 self.robot_arm.StopAllMovement()
105 logging.info('Latency: %s', motopho_thread.latency)
106 logging.info('Correlation: %s', motopho_thread.max_correlation)
107 self._SaveResults(motopho_thread.latency, motopho_thread.max_correlation)
108
109 def _Teardown(self):
110 """Performs any platform-specific teardown."""
111 raise NotImplementedError(
112 'Platform-specific setup must be implemented in subclass')
113
114 def _RunCommand(self, cmd):
115 """Runs the given cmd list and returns its output.
116
117 Prints the command's output and exits if any error occurs.
118
119 Returns:
120 A string containing the stdout and stderr of the command.
121 """
122 try:
123 return subprocess.check_output(cmd, stderr=subprocess.STDOUT)
124 except subprocess.CalledProcessError as e:
125 logging.error('Failed command output: %s', e.output)
126 raise e
127
128 def _SetChromeCommandLineFlags(self, flags):
129 raise NotImplementedError(
130 'Command-line flag setting must be implemented in subclass')
131
132 def _SaveResults(self, latency, correlation):
133 """Saves the results to a JSON file.
134
135 Saved JSON object is compatible with Chrome perf dashboard if
136 put in as the 'chart_data' value.
137 """
138 if not (self.args.output_dir and os.path.isdir(self.args.output_dir)):
139 logging.warning('No output directory set, not saving results to file')
140 return
141
142 latency_trace = {
143 'improvement_direction': 'down',
144 'name': 'latency',
145 'type': 'scalar',
146 'units': 'ms',
147 'value': latency or 999,
148 }
149
150 results = {
151 'format_version': '1.0',
152 'benchmark_name': 'webvr_latency',
153 'benchmark_description': 'Measures the motion-to-photon latency of WebVR',
154 'charts': {
155 self.device_name: {
Lei Lei 2017/04/17 22:57:13 I thought we got agreement to use bot name for dev
bsheedy 2017/04/18 21:17:25 Done. Sample dashboard is https://chromeperf.appsp
Lei Lei 2017/04/20 04:56:20 Nice!
156 'correlation': {
157 'improvement_direction': 'up',
158 'name': 'correlation',
159 'type': 'scalar',
160 'units': '',
161 'value': correlation or -1,
162 },
163 # Points aren't added unless you have a summary trace, and can't seem
164 # to change the summary's name away from the chart name, so duplicate
165 # the latency information
166 'latency': latency_trace,
167 'summary': latency_trace,
168 }
169 }
170 }
171
172 with file(os.path.join(self.args.output_dir,
173 self.args.results_file), 'w') as outfile:
174 json.dump(results, outfile)
175
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698