Commit 91282720 authored by bsheedy's avatar bsheedy Committed by Commit Bot

Add WebVR benchmark using WPR

Adds a new WebVR Telemetry benchmark that runs tests on real world
webpages (as opposed to the synthetic sample site) using WPR (webpage
replay).

Bug: 808597
Change-Id: Ia029d0dcc12d02cc4d33959c285c854c1730178f
Reviewed-on: https://chromium-review.googlesource.com/905783Reviewed-by: default avatarTibor Goldschwendt <tiborg@chromium.org>
Reviewed-by: default avatarKlaus Weidner <klausw@chromium.org>
Commit-Queue: Brian Sheedy <bsheedy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#535122}
parent b7b3a6a4
......@@ -7,12 +7,14 @@ assert(is_android)
group("vr_perf_tests") {
testonly = true
data = [
"./data/",
"./__init__.py",
"./shared_android_vr_page_state.py",
"./vr_benchmarks.py",
"./vr_browsing_mode_pages.py",
"./vr_sample_page.py",
"./webvr_sample_pages.py",
"./webvr_wpr_pages.py",
"//chrome/android/shared_preference_files/test/",
"//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk",
"//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk",
......
*.wpr
*.wprgo
# Generated fetched binary's timestamp
# See details in py_utils.cloud_storage.GetIfChanged(file_path, bucket) method.
*.fetchts
{
"archives": {
"dance_tonite": {
"DEFAULT": "webvr_wpr_000.wprgo"
},
"mass_migrations": {
"DEFAULT": "webvr_wpr_000.wprgo"
},
"sketchfab_pirates_dock": {
"DEFAULT": "webvr_wpr_000.wprgo"
},
"under_neon_lights": {
"DEFAULT": "webvr_wpr_000.wprgo"
},
"within_invasion_ep_1": {
"DEFAULT": "webvr_wpr_000.wprgo"
}
},
"description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.",
"platform_specific": true
}
\ No newline at end of file
72ed936e30184a7338556e4817243ecd1ec924d0
\ No newline at end of file
......@@ -125,3 +125,7 @@ class SharedAndroidVrPageState(shared_page_state.SharedPageState):
@property
def platform(self):
return self._platform
@property
def recording_wpr(self):
return self._finder_options.recording_wpr
......@@ -10,6 +10,7 @@ from telemetry.timeline import chrome_trace_category_filter
from telemetry.timeline import chrome_trace_config
from telemetry.web_perf import timeline_based_measurement
from contrib.vr_benchmarks import webvr_sample_pages
from contrib.vr_benchmarks import webvr_wpr_pages
from contrib.vr_benchmarks import vr_browsing_mode_pages
......@@ -32,11 +33,17 @@ class _BaseVRBenchmark(perf_benchmark.PerfBenchmark):
'This is useful for local testing when turning off the '
'screen leads to locking the phone, which makes Telemetry '
'not produce valid results.')
parser.add_option(
'--recording-wpr',
action='store_true',
default=False,
help='Modifies benchmark behavior slightly while recording WPR files '
'for it. This largely boils down to adding waits/sleeps in order '
'to ensure that enough streaming data is recorded for the '
'benchmark to run without issues.')
@benchmark.Owner(emails=['bsheedy@chromium.org', 'leilei@chromium.org'])
class XrWebVrStatic(_BaseVRBenchmark):
"""Measures WebVR performance with sample pages."""
class _BaseWebVRBenchmark(_BaseVRBenchmark):
SUPPORTED_PLATFORMS = [story.expectations.ALL_ANDROID]
......@@ -56,23 +63,40 @@ class XrWebVrStatic(_BaseVRBenchmark):
chrome_trace_config.MemoryDumpConfig())
return options
def CreateStorySet(self, options):
return webvr_sample_pages.WebVrSamplePageSet()
def SetExtraBrowserOptions(self, options):
memory.SetExtraBrowserOptionsForMemoryMeasurement(options)
options.AppendExtraBrowserArgs([
'--enable-webvr',
])
@classmethod
def ShouldAddValue(cls, name, from_first_story_run):
del from_first_story_run # unused
return memory.DefaultShouldAddValueForMemoryMeasurement(name)
@benchmark.Owner(emails=['bsheedy@chromium.org', 'leilei@chromium.org'])
class XrWebVrStatic(_BaseWebVRBenchmark):
"""Measures WebVR performance with synthetic sample pages."""
def CreateStorySet(self, options):
return webvr_sample_pages.WebVrSamplePageSet()
@classmethod
def Name(cls):
return 'xr.webvr.static'
@benchmark.Owner(emails=['bsheedy@chromium.org', 'tiborg@chromium.org'])
class XrWebVrWprStatic(_BaseWebVRBenchmark):
"""Measures WebVR performance with WPR copies of live websites."""
def CreateStorySet(self, options):
return webvr_wpr_pages.WebVrWprPageSet()
@classmethod
def ShouldAddValue(cls, name, from_first_story_run):
del from_first_story_run # unused
return memory.DefaultShouldAddValueForMemoryMeasurement(name)
def Name(cls):
return 'xr.webvr.wpr.static'
@benchmark.Owner(emails=['tiborg@chromium.org'])
......
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from telemetry import story
from telemetry import page
from contrib.vr_benchmarks import (shared_android_vr_page_state as vr_state)
class WebVrWprPage(page.Page):
"""Class for running a story on a WebVR WPR page."""
def __init__(self, page_set, url, name, interaction_function,
extra_browser_args=None):
"""
Args:
page_set: The StorySet the WebVrWprPage is being added to
url: The URL to navigate to for the story
name: The name of the story
interaction_function: A pointer to a function that takes an ActionRunner
and boolean indicating whether a WPR archive is being recorded. Meant
to handle webpage-specific VR entry
extra_browser_args: Extra browser args that are simply forwarded to
page.Page
"""
super(WebVrWprPage, self).__init__(
url=url,
page_set=page_set,
name=name,
extra_browser_args=extra_browser_args,
shared_page_state_class=vr_state.SharedAndroidVrPageState)
self._shared_page_state = None
self._interaction_function = interaction_function
def RunPageInteractions(self, action_runner):
if self._interaction_function:
self._interaction_function(action_runner, self.recording_wpr)
action_runner.MeasureMemory(True)
action_runner.Navigate("about:blank")
def Run(self, shared_state):
self._shared_page_state = shared_state
super(WebVrWprPage, self).Run(shared_state)
@property
def platform(self):
return self._shared_page_state.platform
@property
def recording_wpr(self):
return self._shared_page_state.recording_wpr
class WebVrWprPageSet(story.StorySet):
"""A page set using live WebVR sites recorded using WPR."""
def __init__(self):
super(WebVrWprPageSet, self).__init__(
archive_data_file='data/webvr_wpr.json',
cloud_storage_bucket=story.PARTNER_BUCKET)
# View the Pirates: Dock model on Sketchfab
def SketchfabInteraction(action_runner, _):
action_runner.WaitForNetworkQuiescence()
action_runner.WaitForElement(selector='a[data-tooltip="View in VR"]')
action_runner.TapElement(selector='a[data-tooltip="View in VR"]')
self.AddStory(WebVrWprPage(
self,
'https://sketchfab.com/models/uFqGJrS9ZjVr9Myk9kg4fubPNPz',
'sketchfab_pirates_dock',
SketchfabInteraction))
# Watch part of the Invasion Episode 1 video on With.in
def WithinInvasionInteraction(action_runner, recording_wpr):
action_runner.WaitForNetworkQuiescence()
action_runner.TapElement(selector='div.play-button')
action_runner.TapElement(selector='div.right.stereo')
# Make sure we get enough streaming video during WPR recording to not run
# into issues when actually running the benchmark
if recording_wpr:
action_runner.Wait(30)
self.AddStory(WebVrWprPage(
self,
# Access the video directly to more easily set resolution and avoid
# iframe weirdness
'https://player.with.in/embed/?id=272&resolution=2880&forced=false&'
'autoplay=true&t=0&internal=true',
'within_invasion_ep_1',
WithinInvasionInteraction))
# Look at "randomly" generated (constant seed) geometry in Mass Migrations
def MassMigrationsInteraction(action_runner, _):
action_runner.WaitForNetworkQuiescence()
# All DOM elements seem to be present on the page from the start, so
# instead wait until the button is actually visible
action_runner.WaitForJavaScriptCondition(
condition='document.querySelector(\'div[id="footer"]\').style.display'
'== "block"')
action_runner.TapElement(selector='a[id="vr"]')
self.AddStory(WebVrWprPage(
self,
# The /iaped is necessary to keep the geometry constant, as it acts as
# the seed for the generator - just visiting the site randomly generates
# geometry
'https://massmigrations.com/iaped',
'mass_migrations',
MassMigrationsInteraction))
# Watch a girl running through a giant forest (I think) in Under Neon Lights
# Note that this is semi-broken in that it doesn't move away from the
# opening when you enter VR, but we're still viewing a relatively complex
# WebGL scene, so it's still useful for perf testing
def UnderNeonLightsInteraction(action_runner, _):
action_runner.WaitForNetworkQuiescence()
# The VR button doesn't have any unique ID or anything, so instead select
# based on the unique text in a child div
action_runner.WaitForElement(text='Start in VR')
action_runner.TapElement(text='Start in VR')
self.AddStory(WebVrWprPage(
self,
# Access the content directly to avoid iframe weirdness
'https://player.with.in/embed/?id=541&resolution=1920&forced=false&'
'autoplay=true&t=0&internal=true',
'under_neon_lights',
UnderNeonLightsInteraction))
# Watch dancing polyhedrons in Dance Tonite
def DanceToniteInteraction(action_runner, _):
action_runner.WaitForNetworkQuiescence()
action_runner.WaitForElement(selector='div.button-play')
action_runner.TapElement(selector='div.button-play')
action_runner.WaitForNetworkQuiescence()
# The VR entry button has no unique text, ID, etc. but does have a child
# SVG with a child path with a unique "d" attribute. It's super long, so
# only match against one part of it
action_runner.WaitForElement(selector='path[d~="M52.6"]')
action_runner.TapElement(selector='path[d~="M52.6"]')
self.AddStory(WebVrWprPage(
self,
'https://tonite.dance',
'dance_tonite',
DanceToniteInteraction))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment