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

Side by Side Diff: tools/perf/profile_creators/fast_navigation_profile_extender.py

Issue 907503002: telemetry: Create a helper class to quickly extend profiles. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments from nednguyen. Created 5 years, 10 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright 2014 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 import time
5
6 from telemetry.core import browser_finder
7 from telemetry.core import browser_finder_exceptions
8 from telemetry.core import exceptions
9 from telemetry.core import util
10
11
12 class FastNavigationProfileExtender(object):
13 """
14 This class creates or extends an existing profile by performing a set of tab
15 navigations in large batches. This is accomplished by opening a large number
16 of tabs, simultaneously navigating all the tabs, and then waiting for all the
17 tabs to load. This provides two benefits:
18 - Takes advantage of the high number of logical cores on modern CPUs.
19 - The total time spent waiting for navigations to time out scales linearly
20 with the number of batches, but does not scale with the size of the
21 batch.
22 """
23 def __init__(self):
24 super(FastNavigationProfileExtender, self).__init__()
25
26 # A reference to the browser that will be performing all of the tab
27 # navigations.
28 self._browser = None
29
30 # A static copy of the urls that this class is going to navigate to.
31 self._navigation_urls = self.NavigationUrls()
nednguyen 2015/02/09 21:35:02 def GetUrlsToNavigate()
erikchen 2015/02/10 00:45:02 Done.
32
33 # The number of tabs to use.
34 self._NUM_TABS = 15
35
36 # The number of pages to load in parallel.
37 self._NUM_PARALLEL_PAGES = 15
38
39 # The amount of time to wait for pages to finish loading.
40 self._PAGE_LOAD_TIMEOUT_IN_SECONDS = 10
41
42 # The amount of time to wait for the retrieval of the URL of a tab.
43 self._TAB_URL_RETRIEVAL_TIMEOUT_IN_SECONDS = 1
44
45 # The amount of time to wait for a navigation to be committed.
46 self._NAVIGATION_COMMIT_WAIT_IN_SECONDS = 0.1
47
48 # A list of tuples (tab, initial_url). A navigation command has been sent
49 # to |tab|. |tab| had a URL of |initial_url| before the command was sent.
50 self._queued_tabs = []
nednguyen 2015/02/09 21:35:02 What about making this a map from tabs to intial_u
erikchen 2015/02/10 00:45:02 That loses the ordering, which matters for perform
nednguyen 2015/02/10 18:48:43 Can you elaborate on why the ordering matters for
erikchen 2015/02/10 21:30:11 Sending commands through the telemetry/Chromium bi
nednguyen 2015/02/10 22:11:37 I want to see real benchmark to justify whether th
erikchen 2015/02/11 02:45:50 There is no optimization here. I'm using a list of
nednguyen 2015/02/12 02:10:53 Hmh, there was context, but the context has change
erikchen 2015/02/12 03:02:58 Your statement "You was using _navigation_url_inde
51
52 # The index of the first url that has not yet been navigated to.
53 self._navigation_url_index = 0
nednguyen 2015/02/09 21:35:02 I don't like having this counter as a class's memb
erikchen 2015/02/10 00:45:02 I've removed this member.
54
55 def Run(self, finder_options):
56 """
57 |finder_options| contains the directory of the input profile, the directory
58 to place the output profile, and sufficient information to choose a specific
59 browser binary.
60 """
61 try:
62 self._BrowserSetup(finder_options)
nednguyen 2015/02/09 21:35:02 s/_BrowserSetup/_SetupBrowser
erikchen 2015/02/10 00:45:02 I've renamed _BrowserSetup to _SetUpBrowser.
63 self._PerformNavigations()
64 except:
nednguyen 2015/02/09 21:35:02 you don't need the "except:\nraise:"
erikchen 2015/02/10 00:45:02 Done.
65 raise
66 finally:
67 self._BrowserTeardown()
nednguyen 2015/02/09 21:35:02 s/_BrowserTeardown/_TeardownBrowser()
erikchen 2015/02/10 00:45:02 I've renamed _BrowserTeardown to _TearDownBrowser.
68
69 def NavigationUrls(self):
70 """
71 Intended for subclass override. Returns a list of urls to be navigated to.
72 """
73 raise NotImplementedError()
74
75
76 def _GetPossibleBrowser(self, finder_options):
77 """Return a possible_browser with the given options."""
78 possible_browser = browser_finder.FindBrowser(finder_options)
79 if not possible_browser:
80 raise browser_finder_exceptions.BrowserFinderException(
81 'No browser found.\n\nAvailable browsers:\n%s\n' %
82 '\n'.join(browser_finder.GetAllAvailableBrowserTypes(finder_options)))
83 finder_options.browser_options.browser_type = (
84 possible_browser.browser_type)
85
86 return possible_browser
87
88 def _RetrieveTabUrl(self, tab):
89 """Retrives the URL of the tab."""
90 try:
91 return tab.EvaluateJavaScript('document.URL',
92 self._TAB_URL_RETRIEVAL_TIMEOUT_IN_SECONDS)
93 except exceptions.DevtoolsTargetCrashException:
94 return None
95
96 def _BatchNavigateTabs(self):
97 """Performs a batch of tab navigations with minimal delay."""
98 max_index = min(self._navigation_url_index + self._NUM_PARALLEL_PAGES,
99 len(self._navigation_urls))
100 timeout_in_seconds = 0
101
102 for i in range(self._navigation_url_index, max_index):
103 url = self._navigation_urls[i]
104 tab = self._browser.tabs[i % self._NUM_TABS]
105 initial_url = self._RetrieveTabUrl(tab)
106
107 try:
108 tab.Navigate(url, None, timeout_in_seconds)
109 except exceptions.DevtoolsTargetCrashException:
110 # We expect a time out, and don't mind if the webpage crashes. Ignore
111 # both exceptions.
112 pass
113
114 self._queued_tabs.append((tab, initial_url))
115 self._navigation_url_index = max_index
116
117 def _WaitForQueuedTabsToLoad(self):
118 """Waits for all the batch navigated tabs to finish loading."""
119 end_time = time.time() + self._PAGE_LOAD_TIMEOUT_IN_SECONDS
120 for tab, initial_url in self._queued_tabs:
121 seconds_to_wait = end_time - time.time()
122 seconds_to_wait = max(0, seconds_to_wait)
123
124 if seconds_to_wait == 0:
125 break
126
127 # Since we don't wait any time for the tab url navigation to commit, it's
128 # possible that the tab hasn't started navigating yet.
129 current_url = self._RetrieveTabUrl(tab)
130
131 if current_url == initial_url:
132 # If the navigation hasn't been committed yet, wait a small amount of
133 # time. Don't bother rechecking the condition, since it's also possible
134 # that the web page isn't processing javascript.
135 time.sleep(self._NAVIGATION_COMMIT_WAIT_IN_SECONDS)
136
137 try:
138 tab.WaitForDocumentReadyStateToBeComplete(seconds_to_wait)
139 except (util.TimeoutException, exceptions.DevtoolsTargetCrashException):
140 # Ignore time outs and web page crashes.
141 pass
142 self._queued_tabs = []
143
144 def _BrowserSetup(self, finder_options):
145 """
146 Finds the browser, starts the browser, and opens the requisite number of
147 tabs.
148 """
149 possible_browser = self._GetPossibleBrowser(finder_options)
150 self._browser = possible_browser.Create(finder_options)
151
152 for _ in range(self._NUM_TABS):
153 self._browser.tabs.New()
154
155 def _PerformNavigations(self):
156 """
157 Performs the navigations specified by |_navigation_urls| in large batches.
158 """
159 while True:
160 self._BatchNavigateTabs()
161 self._WaitForQueuedTabsToLoad()
162
163 if self._navigation_url_index == len(self._navigation_urls):
164 break
165
166 def _BrowserTeardown(self):
167 """
168 Teardown that is guaranteed to be executed before the instance is destroyed.
169 """
170 if self._browser:
171 self._browser.Close()
172 self._browser = None
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698