OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 #include "chrome_frame/test/perf/chrome_frame_perftest.h" | |
6 | |
7 #include <atlhost.h> | |
8 #include <atlwin.h> | |
9 | |
10 #include <map> | |
11 #include <string> | |
12 #include <vector> | |
13 | |
14 #include "base/debug/trace_event_win.h" | |
15 #include "base/file_util.h" | |
16 #include "base/files/file_path.h" | |
17 #include "base/memory/scoped_ptr.h" | |
18 #include "base/path_service.h" | |
19 #include "base/process/kill.h" | |
20 #include "base/process/launch.h" | |
21 #include "base/process/process_iterator.h" | |
22 #include "base/strings/string_util.h" | |
23 #include "base/strings/stringprintf.h" | |
24 #include "base/strings/utf_string_conversions.h" | |
25 #include "base/test/perf_time_logger.h" | |
26 #include "base/test/test_file_util.h" | |
27 #include "base/threading/platform_thread.h" | |
28 #include "base/time/time.h" | |
29 #include "base/win/event_trace_consumer.h" | |
30 #include "base/win/event_trace_controller.h" | |
31 #include "base/win/registry.h" | |
32 #include "base/win/scoped_bstr.h" | |
33 #include "base/win/scoped_comptr.h" | |
34 #include "base/win/scoped_variant.h" | |
35 #include "chrome/app/image_pre_reader_win.h" | |
36 #include "chrome/common/chrome_constants.h" | |
37 #include "chrome/common/chrome_paths.h" | |
38 #include "chrome/common/chrome_paths_internal.h" | |
39 #include "chrome/test/base/chrome_process_util.h" | |
40 #include "chrome/test/ui/ui_perf_test.h" | |
41 #include "chrome_frame/chrome_tab.h" | |
42 #include "chrome_frame/test_utils.h" | |
43 #include "chrome_frame/utils.h" | |
44 #include "testing/perf/perf_test.h" | |
45 | |
46 const wchar_t kSilverlightControlKey[] = | |
47 L"CLSID\\{DFEAF541-F3E1-4c24-ACAC-99C30715084A}\\InprocServer32"; | |
48 | |
49 const wchar_t kFlashControlKey[] = | |
50 L"CLSID\\{D27CDB6E-AE6D-11cf-96B8-444553540000}\\InprocServer32"; | |
51 | |
52 using base::TimeDelta; | |
53 using base::TimeTicks; | |
54 | |
55 // This class implements an ActiveX container which hosts the ChromeFrame | |
56 // ActiveX control. It provides hooks which can be implemented by derived | |
57 // classes for implementing performance measurement, etc. | |
58 class ChromeFrameActiveXContainer | |
59 : public CWindowImpl<ChromeFrameActiveXContainer, CWindow, CWinTraits < | |
60 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, | |
61 WS_EX_APPWINDOW | WS_EX_WINDOWEDGE> >, | |
62 public CComObjectRootEx<CComSingleThreadModel>, | |
63 public IPropertyNotifySink { | |
64 public: | |
65 ~ChromeFrameActiveXContainer() { | |
66 if (m_hWnd) | |
67 DestroyWindow(); | |
68 } | |
69 | |
70 DECLARE_WND_CLASS_EX(L"ChromeFrameActiveX_container", 0, 0) | |
71 | |
72 BEGIN_COM_MAP(ChromeFrameActiveXContainer) | |
73 COM_INTERFACE_ENTRY(IPropertyNotifySink) | |
74 END_COM_MAP() | |
75 | |
76 BEGIN_MSG_MAP(ChromeFrameActiveXContainer) | |
77 MESSAGE_HANDLER(WM_CREATE, OnCreate) | |
78 MESSAGE_HANDLER(WM_DESTROY, OnDestroy) | |
79 END_MSG_MAP() | |
80 | |
81 HRESULT OnMessageCallback(const VARIANT* param) { | |
82 DVLOG(1) << __FUNCTION__; | |
83 OnMessageCallbackImpl(param); | |
84 return S_OK; | |
85 } | |
86 | |
87 HRESULT OnLoadErrorCallback(const VARIANT* param) { | |
88 DVLOG(1) << __FUNCTION__ << " " << param->bstrVal; | |
89 OnLoadErrorCallbackImpl(param); | |
90 return S_OK; | |
91 } | |
92 | |
93 HRESULT OnLoadCallback(const VARIANT* param) { | |
94 DVLOG(1) << __FUNCTION__ << " " << param->bstrVal; | |
95 OnLoadCallbackImpl(param); | |
96 return S_OK; | |
97 } | |
98 | |
99 ChromeFrameActiveXContainer() : | |
100 prop_notify_cookie_(0), | |
101 onmsg_(this, &ChromeFrameActiveXContainer::OnMessageCallback), | |
102 onloaderror_(this, &ChromeFrameActiveXContainer::OnLoadErrorCallback), | |
103 onload_(this, &ChromeFrameActiveXContainer::OnLoadCallback) { | |
104 } | |
105 | |
106 LRESULT OnCreate(UINT , WPARAM , LPARAM , BOOL& ) { | |
107 chromeview_.Attach(m_hWnd); | |
108 return 0; | |
109 } | |
110 | |
111 // This will be called twice. | |
112 // Once from CAxHostWindow::OnDestroy (through DefWindowProc) | |
113 // and once more from the ATL since CAxHostWindow::OnDestroy claims the | |
114 // message is not handled. | |
115 LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& handled) { // NOLINT | |
116 if (prop_notify_cookie_) { | |
117 AtlUnadvise(tab_, IID_IPropertyNotifySink, prop_notify_cookie_); | |
118 prop_notify_cookie_ = 0; | |
119 } | |
120 | |
121 tab_.Release(); | |
122 return 0; | |
123 } | |
124 | |
125 virtual void OnFinalMessage(HWND /*hWnd*/) { | |
126 ::PostQuitMessage(6); | |
127 } | |
128 | |
129 static const wchar_t* GetWndCaption() { | |
130 return L"ChromeFrame Container"; | |
131 } | |
132 | |
133 // IPropertyNotifySink | |
134 STDMETHOD(OnRequestEdit)(DISPID disp_id) { | |
135 OnRequestEditImpl(disp_id); | |
136 return S_OK; | |
137 } | |
138 | |
139 STDMETHOD(OnChanged)(DISPID disp_id) { | |
140 if (disp_id != DISPID_READYSTATE) | |
141 return S_OK; | |
142 | |
143 long ready_state; | |
144 HRESULT hr = tab_->get_readyState(&ready_state); | |
145 DCHECK(hr == S_OK); | |
146 | |
147 OnReadyStateChanged(ready_state); | |
148 | |
149 if (ready_state == READYSTATE_COMPLETE) { | |
150 if (!starting_url_.empty()) { | |
151 Navigate(starting_url_.c_str()); | |
152 } else { | |
153 PostMessage(WM_CLOSE); | |
154 } | |
155 } else if (ready_state == READYSTATE_UNINITIALIZED) { | |
156 DLOG(ERROR) << __FUNCTION__ << " Chrome launch failed."; | |
157 } | |
158 | |
159 return S_OK; | |
160 } | |
161 | |
162 void CreateChromeFrameWindow(const std::string& starting_url) { | |
163 starting_url_ = starting_url; | |
164 RECT rc = { 0, 0, 800, 600 }; | |
165 Create(NULL, rc); | |
166 DCHECK(m_hWnd); | |
167 ShowWindow(SW_SHOWDEFAULT); | |
168 } | |
169 | |
170 void CreateControl(bool setup_event_sinks) { | |
171 HRESULT hr = chromeview_.CreateControl(L"ChromeTab.ChromeFrame"); | |
172 EXPECT_HRESULT_SUCCEEDED(hr); | |
173 hr = chromeview_.QueryControl(tab_.Receive()); | |
174 EXPECT_HRESULT_SUCCEEDED(hr); | |
175 | |
176 if (setup_event_sinks) | |
177 SetupEventSinks(); | |
178 } | |
179 | |
180 void Navigate(const char* url) { | |
181 BeforeNavigateImpl(url); | |
182 | |
183 HRESULT hr = | |
184 tab_->put_src(base::win::ScopedBstr(base::UTF8ToWide(url).c_str())); | |
185 DCHECK(hr == S_OK) << "Chrome frame NavigateToURL(" << url | |
186 << base::StringPrintf(L") failed 0x%08X", hr); | |
187 } | |
188 | |
189 void SetupEventSinks() { | |
190 HRESULT hr = AtlAdvise(tab_, this, IID_IPropertyNotifySink, | |
191 &prop_notify_cookie_); | |
192 DCHECK(hr == S_OK) << "AtlAdvice for IPropertyNotifySink failed " << hr; | |
193 | |
194 base::win::ScopedVariant onmessage(onmsg_.ToDispatch()); | |
195 base::win::ScopedVariant onloaderror(onloaderror_.ToDispatch()); | |
196 base::win::ScopedVariant onload(onload_.ToDispatch()); | |
197 EXPECT_HRESULT_SUCCEEDED(tab_->put_onmessage(onmessage)); | |
198 EXPECT_HRESULT_SUCCEEDED(tab_->put_onloaderror(onloaderror)); | |
199 EXPECT_HRESULT_SUCCEEDED(tab_->put_onload(onload)); | |
200 } | |
201 | |
202 protected: | |
203 // These functions are implemented by derived classes for special behavior | |
204 // like performance measurement, etc. | |
205 virtual void OnReadyStateChanged(long ready_state) {} | |
206 virtual void OnRequestEditImpl(DISPID disp_id) {} | |
207 | |
208 virtual void OnMessageCallbackImpl(const VARIANT* param) {} | |
209 | |
210 virtual void OnLoadCallbackImpl(const VARIANT* param) { | |
211 PostMessage(WM_CLOSE); | |
212 } | |
213 | |
214 virtual void OnLoadErrorCallbackImpl(const VARIANT* param) { | |
215 PostMessage(WM_CLOSE); | |
216 } | |
217 virtual void BeforeNavigateImpl(const char* url) {} | |
218 | |
219 CAxWindow chromeview_; | |
220 base::win::ScopedComPtr<IChromeFrame> tab_; | |
221 DWORD prop_notify_cookie_; | |
222 DispCallback<ChromeFrameActiveXContainer> onmsg_; | |
223 DispCallback<ChromeFrameActiveXContainer> onloaderror_; | |
224 DispCallback<ChromeFrameActiveXContainer> onload_; | |
225 std::string starting_url_; | |
226 }; | |
227 | |
228 // This class overrides the hooks provided by the ChromeFrameActiveXContainer | |
229 // class and measures performance at various stages, like initialzation of | |
230 // the Chrome frame widget, navigation, etc. | |
231 class ChromeFrameActiveXContainerPerf : public ChromeFrameActiveXContainer { | |
232 public: | |
233 ChromeFrameActiveXContainerPerf() {} | |
234 | |
235 void CreateControl(bool setup_event_sinks) { | |
236 perf_initialize_.reset(new base::PerfTimeLogger("Fully initialized")); | |
237 base::PerfTimeLogger perf_create("Create Control"); | |
238 | |
239 HRESULT hr = chromeview_.CreateControl(L"ChromeTab.ChromeFrame"); | |
240 EXPECT_HRESULT_SUCCEEDED(hr); | |
241 hr = chromeview_.QueryControl(tab_.Receive()); | |
242 EXPECT_HRESULT_SUCCEEDED(hr); | |
243 | |
244 perf_create.Done(); | |
245 if (setup_event_sinks) | |
246 SetupEventSinks(); | |
247 } | |
248 | |
249 protected: | |
250 virtual void OnReadyStateChanged(long ready_state) { | |
251 // READYSTATE_COMPLETE is fired when the automation server is ready. | |
252 if (ready_state == READYSTATE_COMPLETE) { | |
253 perf_initialize_->Done(); | |
254 } else if (ready_state == READYSTATE_INTERACTIVE) { | |
255 // Window ready. Currently we never receive this notification because it | |
256 // is fired before we finish setting up our hosting environment. | |
257 // This is because of how ATL is written. Moving forward we might | |
258 // have our own hosting classes and then have more control over when we | |
259 // set up the prop notify sink. | |
260 } else { | |
261 DCHECK(ready_state != READYSTATE_UNINITIALIZED) << "failed to initialize"; | |
262 } | |
263 } | |
264 | |
265 virtual void OnLoadCallbackImpl(const VARIANT* param) { | |
266 PostMessage(WM_CLOSE); | |
267 perf_navigate_->Done(); | |
268 } | |
269 | |
270 virtual void OnLoadErrorCallbackImpl(const VARIANT* param) { | |
271 PostMessage(WM_CLOSE); | |
272 perf_navigate_->Done(); | |
273 } | |
274 | |
275 virtual void BeforeNavigateImpl(const char* url ) { | |
276 std::string test_name = "Navigate "; | |
277 test_name += url; | |
278 perf_navigate_.reset(new base::PerfTimeLogger(test_name.c_str())); | |
279 } | |
280 | |
281 scoped_ptr<base::PerfTimeLogger> perf_initialize_; | |
282 scoped_ptr<base::PerfTimeLogger> perf_navigate_; | |
283 }; | |
284 | |
285 // This class provides common functionality which can be used for most of the | |
286 // ChromeFrame/Tab performance tests. | |
287 class ChromeFramePerfTestBase : public UIPerfTest { | |
288 public: | |
289 ChromeFramePerfTestBase() {} | |
290 protected: | |
291 scoped_ptr<ScopedChromeFrameRegistrar> chrome_frame_registrar_; | |
292 }; | |
293 | |
294 class ChromeFrameStartupTest : public ChromeFramePerfTestBase { | |
295 public: | |
296 ChromeFrameStartupTest() {} | |
297 | |
298 virtual void SetUp() { | |
299 ASSERT_TRUE(PathService::Get(chrome::DIR_APP, &dir_app_)); | |
300 | |
301 chrome_dll_ = dir_app_.Append(L"chrome.dll"); | |
302 chrome_exe_ = dir_app_.Append(chrome::kBrowserProcessExecutableName); | |
303 chrome_frame_dll_ = dir_app_.Append(kChromeFrameDllName); | |
304 icu_dll_ = dir_app_.Append(L"icudt.dll"); | |
305 ffmpegsumo_dll_ = dir_app_.Append(L"ffmpegsumo.dll"); | |
306 } | |
307 | |
308 // TODO(iyengar) | |
309 // This function is similar to the RunStartupTest function used in chrome | |
310 // startup tests. Refactor into a common implementation. | |
311 void RunStartupTest(const char* graph, const char* trace, | |
312 const char* startup_url, bool test_cold, | |
313 int total_binaries, | |
314 const base::FilePath binaries_to_evict[], | |
315 bool important, bool ignore_cache_error) { | |
316 const int kNumCycles = 20; | |
317 | |
318 startup_url_ = startup_url; | |
319 | |
320 TimeDelta timings[kNumCycles]; | |
321 | |
322 for (int i = 0; i < kNumCycles; ++i) { | |
323 if (test_cold) { | |
324 for (int binary_index = 0; binary_index < total_binaries; | |
325 binary_index++) { | |
326 bool result = base::EvictFileFromSystemCacheWithRetry( | |
327 binaries_to_evict[binary_index]); | |
328 if (!ignore_cache_error) { | |
329 ASSERT_TRUE(result); | |
330 } else if (!result) { | |
331 LOG(ERROR) << GetLastError(); | |
332 printf("\nFailed to evict file %ls from cache. Not running test\n", | |
333 binaries_to_evict[binary_index].value().c_str()); | |
334 return; | |
335 } | |
336 } | |
337 } | |
338 | |
339 TimeTicks start_time, end_time; | |
340 | |
341 RunStartupTestImpl(&start_time, &end_time); | |
342 | |
343 timings[i] = end_time - start_time; | |
344 | |
345 CoFreeUnusedLibraries(); | |
346 | |
347 // TODO(beng): Can't shut down so quickly. Figure out why, and fix. If we | |
348 // do, we crash. | |
349 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50)); | |
350 } | |
351 | |
352 std::string times; | |
353 for (int i = 0; i < kNumCycles; ++i) | |
354 base::StringAppendF(×, "%.2f,", timings[i].InMillisecondsF()); | |
355 | |
356 perf_test::PrintResultList(graph, "", trace, times, "ms", important); | |
357 } | |
358 | |
359 base::FilePath dir_app_; | |
360 base::FilePath chrome_dll_; | |
361 base::FilePath chrome_exe_; | |
362 base::FilePath chrome_frame_dll_; | |
363 base::FilePath icu_dll_; | |
364 base::FilePath ffmpegsumo_dll_; | |
365 | |
366 protected: | |
367 // Individual startup tests should implement this function. | |
368 virtual void RunStartupTestImpl(TimeTicks* start_time, | |
369 TimeTicks* end_time) {} | |
370 | |
371 // The host is torn down by this function. It should not be used after | |
372 // this function returns. | |
373 static void ReleaseHostComReferences(CAxWindow& host) { | |
374 CComPtr<IAxWinHostWindow> spWinHost; | |
375 host.QueryHost(&spWinHost); | |
376 ASSERT_TRUE(spWinHost != NULL); | |
377 | |
378 // Hack to get the host to release all interfaces and thus ensure that | |
379 // the COM server can be unloaded. | |
380 CAxHostWindow* host_window = static_cast<CAxHostWindow*>(spWinHost.p); | |
381 host_window->ReleaseAll(); | |
382 host.DestroyWindow(); | |
383 } | |
384 | |
385 std::string startup_url_; | |
386 }; | |
387 | |
388 class ChromeFrameStartupTestActiveX : public ChromeFrameStartupTest { | |
389 public: | |
390 virtual void SetUp() { | |
391 // Register the Chrome Frame DLL in the build directory. | |
392 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar( | |
393 ScopedChromeFrameRegistrar::SYSTEM_LEVEL)); | |
394 | |
395 ChromeFrameStartupTest::SetUp(); | |
396 } | |
397 | |
398 protected: | |
399 virtual void RunStartupTestImpl(TimeTicks* start_time, | |
400 TimeTicks* end_time) { | |
401 *start_time = TimeTicks::Now(); | |
402 SimpleModule module; | |
403 AtlAxWinInit(); | |
404 CComObjectStackEx<ChromeFrameActiveXContainer> wnd; | |
405 wnd.CreateChromeFrameWindow(startup_url_); | |
406 wnd.CreateControl(true); | |
407 module.RunMessageLoop(); | |
408 *end_time = TimeTicks::Now(); | |
409 } | |
410 }; | |
411 | |
412 // This class measures the load time of chrome and chrome frame binaries | |
413 class ChromeFrameBinariesLoadTest : public ChromeFrameStartupTestActiveX { | |
414 static const size_t kStepSize = 4 * 1024; | |
415 public: | |
416 enum PreReadType { | |
417 kPreReadNone, | |
418 kPreReadPartial, | |
419 kPreReadFull | |
420 }; | |
421 | |
422 ChromeFrameBinariesLoadTest() | |
423 : pre_read_type_(kPreReadNone), | |
424 step_size_(kStepSize), | |
425 bytes_to_read_(0), | |
426 percentage_to_preread_(25) {} | |
427 | |
428 protected: | |
429 virtual void RunStartupTestImpl(TimeTicks* start_time, | |
430 TimeTicks* end_time) { | |
431 *start_time = TimeTicks::Now(); | |
432 | |
433 if (pre_read_type_ == kPreReadFull) { | |
434 EXPECT_TRUE(ImagePreReader::PreReadImage(chrome_exe_.value().c_str(), | |
435 bytes_to_read_, | |
436 step_size_)); | |
437 EXPECT_TRUE(ImagePreReader::PreReadImage(chrome_dll_.value().c_str(), | |
438 bytes_to_read_, | |
439 step_size_)); | |
440 } else if (pre_read_type_ == kPreReadPartial) { | |
441 EXPECT_TRUE( | |
442 ImagePreReader::PartialPreReadImage(chrome_exe_.value().c_str(), | |
443 percentage_to_preread_, | |
444 step_size_)); | |
445 EXPECT_TRUE( | |
446 ImagePreReader::PartialPreReadImage(chrome_dll_.value().c_str(), | |
447 percentage_to_preread_, | |
448 step_size_)); | |
449 } | |
450 | |
451 HMODULE chrome_exe = LoadLibrary(chrome_exe_.value().c_str()); | |
452 EXPECT_TRUE(chrome_exe != NULL); | |
453 | |
454 HMODULE chrome_dll = LoadLibrary(chrome_dll_.value().c_str()); | |
455 EXPECT_TRUE(chrome_dll != NULL); | |
456 | |
457 *end_time = TimeTicks::Now(); | |
458 | |
459 FreeLibrary(chrome_exe); | |
460 FreeLibrary(chrome_dll); | |
461 } | |
462 | |
463 PreReadType pre_read_type_; | |
464 size_t bytes_to_read_; | |
465 size_t step_size_; | |
466 uint8 percentage_to_preread_; | |
467 }; | |
468 | |
469 // This class provides functionality to run the startup performance test for | |
470 // the ChromeFrame ActiveX against a reference build. At this point we only run | |
471 // this test in warm mode. | |
472 class ChromeFrameStartupTestActiveXReference | |
473 : public ChromeFrameStartupTestActiveX { | |
474 public: | |
475 // override the browser directory to use the reference build instead. | |
476 virtual void SetUp() { | |
477 // Register the reference build Chrome Frame DLL. | |
478 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar( | |
479 ScopedChromeFrameRegistrar::SYSTEM_LEVEL)); | |
480 chrome_frame_registrar_->RegisterReferenceChromeFrameBuild(); | |
481 | |
482 ChromeFrameStartupTest::SetUp(); | |
483 | |
484 chrome_frame_dll_ = base::FilePath( | |
485 chrome_frame_registrar_->GetReferenceChromeFrameDllPath()); | |
486 DVLOG(1) << __FUNCTION__ << ": " << chrome_frame_dll_.value(); | |
487 } | |
488 | |
489 virtual void TearDown() { | |
490 // Reregister the Chrome Frame DLL in the build directory. | |
491 chrome_frame_registrar_.reset(NULL); | |
492 } | |
493 }; | |
494 | |
495 // This class provides base functionality to measure ChromeFrame memory | |
496 // usage. | |
497 // TODO(iyengar) | |
498 // Some of the functionality in this class like printing the results, etc | |
499 // is based on the chrome\test\memory_test.cc. We need to factor out | |
500 // the common code. | |
501 class ChromeFrameMemoryTest : public ChromeFramePerfTestBase { | |
502 // Contains information about the memory consumption of a process. | |
503 class ProcessMemoryInfo { | |
504 public: | |
505 // Default constructor | |
506 // Added to enable us to add ProcessMemoryInfo instances to a map. | |
507 ProcessMemoryInfo() | |
508 : process_id_(0), | |
509 virtual_size_(0), | |
510 working_set_size_(0), | |
511 chrome_browser_process_(false), | |
512 chrome_frame_memory_test_instance_(NULL) {} | |
513 | |
514 ProcessMemoryInfo(base::ProcessId process_id, bool chrome_browser_process, | |
515 ChromeFrameMemoryTest* memory_test_instance) | |
516 : process_id_(process_id), | |
517 virtual_size_(0), | |
518 working_set_size_(0), | |
519 chrome_browser_process_(chrome_browser_process), | |
520 chrome_frame_memory_test_instance_(memory_test_instance) {} | |
521 | |
522 bool GetMemoryConsumptionDetails() { | |
523 base::ProcessHandle process_handle; | |
524 if (!base::OpenPrivilegedProcessHandle(process_id_, &process_handle)) { | |
525 NOTREACHED(); | |
526 } | |
527 | |
528 // TODO(sgk): if/when base::ProcessMetrics can return real memory | |
529 // stats on mac, convert to: | |
530 // | |
531 // scoped_ptr<base::ProcessMetrics> process_metrics; | |
532 // process_metrics.reset( | |
533 // base::ProcessMetrics::CreateProcessMetrics(process_handle)); | |
534 scoped_ptr<ChromeTestProcessMetrics> process_metrics; | |
535 process_metrics.reset( | |
536 ChromeTestProcessMetrics::CreateProcessMetrics(process_handle)); | |
537 | |
538 virtual_size_ = process_metrics->GetPagefileUsage(); | |
539 working_set_size_ = process_metrics->GetWorkingSetSize(); | |
540 | |
541 base::CloseProcessHandle(process_handle); | |
542 return true; | |
543 } | |
544 | |
545 void Print(const char* test_name) { | |
546 std::string trace_name(test_name); | |
547 | |
548 ASSERT_TRUE(chrome_frame_memory_test_instance_ != NULL); | |
549 | |
550 if (chrome_browser_process_) { | |
551 perf_test::PrintResult("vm_final_browser", "", trace_name + "_vm_b", | |
552 virtual_size_ / 1024, "KB", false /* not important */); | |
553 perf_test::PrintResult("ws_final_browser", "", trace_name + "_ws_b", | |
554 working_set_size_ / 1024, "KB", false /* not important */); | |
555 } else if (process_id_ == base::GetCurrentProcId()) { | |
556 perf_test::PrintResult("vm_current_process", "", trace_name + "_vm_c", | |
557 virtual_size_ / 1024, "KB", false /* not important */); | |
558 perf_test::PrintResult("ws_current_process", "", trace_name + "_ws_c", | |
559 working_set_size_ / 1024, "KB", false /* not important */); | |
560 } | |
561 | |
562 printf("\n"); | |
563 } | |
564 | |
565 base::ProcessId process_id_; | |
566 size_t virtual_size_; | |
567 size_t working_set_size_; | |
568 // Set to true if this is the chrome browser process. | |
569 bool chrome_browser_process_; | |
570 | |
571 // A reference to the ChromeFrameMemoryTest instance. Used to print memory | |
572 // consumption information. | |
573 ChromeFrameMemoryTest* chrome_frame_memory_test_instance_; | |
574 }; | |
575 | |
576 // This map tracks memory usage for a process. It is keyed on the process | |
577 // id. | |
578 typedef std::map<DWORD, ProcessMemoryInfo> ProcessMemoryConsumptionMap; | |
579 | |
580 public: | |
581 ChromeFrameMemoryTest() : current_url_index_(0) { | |
582 } | |
583 | |
584 virtual void SetUp() { | |
585 // Register the Chrome Frame DLL in the build directory. | |
586 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar( | |
587 ScopedChromeFrameRegistrar::SYSTEM_LEVEL)); | |
588 } | |
589 | |
590 void RunTest(const char* test_name, char* urls[], int total_urls) { | |
591 ASSERT_TRUE(urls != NULL); | |
592 ASSERT_GT(total_urls, 0); | |
593 | |
594 // Record the initial CommitCharge. This is a system-wide measurement, | |
595 // so if other applications are running, they can create variance in this | |
596 // test. | |
597 start_commit_charge_ = base::GetSystemCommitCharge(); | |
598 | |
599 for (int i = 0; i < total_urls; i++) | |
600 urls_.push_back(urls[i]); | |
601 | |
602 std::string url; | |
603 GetNextUrl(&url); | |
604 ASSERT_TRUE(!url.empty()); | |
605 | |
606 StartTest(url, test_name); | |
607 } | |
608 | |
609 void OnNavigationSuccess(const VARIANT* param) { | |
610 ASSERT_TRUE(param != NULL); | |
611 ASSERT_EQ(VT_BSTR, param->vt); | |
612 | |
613 DVLOG(1) << __FUNCTION__ << " " << param->bstrVal; | |
614 InitiateNextNavigation(); | |
615 } | |
616 | |
617 void OnNavigationFailure(const VARIANT* param) { | |
618 ASSERT_TRUE(param != NULL); | |
619 ASSERT_EQ(VT_BSTR, param->vt); | |
620 | |
621 DVLOG(1) << __FUNCTION__ << " " << param->bstrVal; | |
622 InitiateNextNavigation(); | |
623 } | |
624 | |
625 protected: | |
626 bool GetNextUrl(std::string* url) { | |
627 if (current_url_index_ >= urls_.size()) | |
628 return false; | |
629 | |
630 *url = urls_[current_url_index_++]; | |
631 return true; | |
632 } | |
633 | |
634 void InitiateNextNavigation() { | |
635 // Get the memory consumption information for the child processes | |
636 // of the chrome browser. | |
637 ChromeProcessList child_processes = GetBrowserChildren(); | |
638 ChromeProcessList::iterator index; | |
639 for (index = child_processes.begin(); index != child_processes.end(); | |
640 ++index) { | |
641 AccountProcessMemoryUsage(*index); | |
642 } | |
643 | |
644 // TODO(iyengar): Bug 2953 | |
645 // Need to verify if this is still true. | |
646 // The automation crashes periodically if we cycle too quickly. | |
647 // To make these tests more reliable, slowing them down a bit. | |
648 Sleep(200); | |
649 | |
650 std::string url; | |
651 bool next_url = GetNextUrl(&url); | |
652 if (!url.empty()) { | |
653 NavigateImpl(url); | |
654 } else { | |
655 TestCompleted(); | |
656 } | |
657 } | |
658 | |
659 void PrintResults(const char* test_name) { | |
660 PrintMemoryUsageInfo(test_name); | |
661 memory_consumption_map_.clear(); | |
662 | |
663 // Added to give the OS some time to flush the used pages for the | |
664 // chrome processes which would have exited by now. | |
665 Sleep(200); | |
666 | |
667 size_t end_commit_charge = base::GetSystemCommitCharge(); | |
668 size_t commit_size = (end_commit_charge - start_commit_charge_) * 1024; | |
669 | |
670 std::string trace_name(test_name); | |
671 trace_name.append("_cc"); | |
672 | |
673 perf_test::PrintResult("commit_charge", "", trace_name, | |
674 commit_size / 1024, "KB", true /* important */); | |
675 printf("\n"); | |
676 } | |
677 | |
678 base::ProcessId chrome_browser_process_id() { | |
679 base::NamedProcessIterator iter(L"chrome.exe", NULL); | |
680 const base::ProcessEntry* entry = iter.NextProcessEntry(); | |
681 if (entry) { | |
682 return entry->pid(); | |
683 } | |
684 return -1; | |
685 } | |
686 | |
687 ChromeProcessList GetBrowserChildren() { | |
688 ChromeProcessList list = GetRunningChromeProcesses( | |
689 chrome_browser_process_id()); | |
690 ChromeProcessList::iterator browser = | |
691 std::find(list.begin(), list.end(), chrome_browser_process_id()); | |
692 if (browser != list.end()) { | |
693 list.erase(browser); | |
694 } | |
695 return list; | |
696 } | |
697 | |
698 void AccountProcessMemoryUsage(DWORD process_id) { | |
699 ProcessMemoryInfo process_memory_info( | |
700 process_id, process_id == chrome_browser_process_id(), this); | |
701 | |
702 ASSERT_TRUE(process_memory_info.GetMemoryConsumptionDetails()); | |
703 | |
704 memory_consumption_map_[process_id] = process_memory_info; | |
705 } | |
706 | |
707 void PrintMemoryUsageInfo(const char* test_name) { | |
708 printf("\n"); | |
709 | |
710 std::string trace_name(test_name); | |
711 | |
712 ProcessMemoryConsumptionMap::iterator index; | |
713 size_t total_virtual_size = 0; | |
714 size_t total_working_set_size = 0; | |
715 | |
716 for (index = memory_consumption_map_.begin(); | |
717 index != memory_consumption_map_.end(); | |
718 ++index) { | |
719 ProcessMemoryInfo& memory_info = (*index).second; | |
720 memory_info.Print(test_name); | |
721 | |
722 total_virtual_size += memory_info.virtual_size_; | |
723 total_working_set_size += memory_info.working_set_size_; | |
724 } | |
725 | |
726 printf("\n"); | |
727 | |
728 perf_test::PrintResult("vm_final_total", "", trace_name + "_vm", | |
729 total_virtual_size / 1024, "KB", | |
730 false /* not important */); | |
731 perf_test::PrintResult("ws_final_total", "", trace_name + "_ws", | |
732 total_working_set_size / 1024, "KB", | |
733 true /* important */); | |
734 } | |
735 | |
736 // Should never get called. | |
737 virtual void StartTest(const std::string& url, | |
738 const std::string& test_name) = 0 { | |
739 ASSERT_FALSE(false); | |
740 } | |
741 | |
742 // Should never get called. | |
743 virtual void NavigateImpl(const std::string& url) = 0 { | |
744 ASSERT_FALSE(false); | |
745 } | |
746 | |
747 virtual void TestCompleted() = 0 { | |
748 ASSERT_FALSE(false); | |
749 } | |
750 | |
751 // Holds the commit charge in KBytes at the start of the memory test run. | |
752 size_t start_commit_charge_; | |
753 | |
754 // The index of the URL being tested. | |
755 size_t current_url_index_; | |
756 | |
757 // Contains the list of urls against which the tests are run. | |
758 std::vector<std::string> urls_; | |
759 | |
760 ProcessMemoryConsumptionMap memory_consumption_map_; | |
761 }; | |
762 | |
763 // This class provides functionality to run the memory test against a reference | |
764 // chrome frame build. | |
765 class ChromeFrameMemoryTestReference : public ChromeFrameMemoryTest { | |
766 public: | |
767 virtual void SetUp() { | |
768 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar( | |
769 ScopedChromeFrameRegistrar::SYSTEM_LEVEL)); | |
770 chrome_frame_registrar_->RegisterReferenceChromeFrameBuild(); | |
771 } | |
772 | |
773 virtual void TearDown() { | |
774 // Reregisters the chrome frame DLL in the build directory. | |
775 chrome_frame_registrar_.reset(NULL); | |
776 } | |
777 }; | |
778 | |
779 // This class overrides the hooks provided by the ChromeFrameActiveXContainer | |
780 // class and calls back into the ChromeFrameMemoryTest object instance, | |
781 // which measures ChromeFrame memory usage. | |
782 class ChromeFrameActiveXContainerMemory : public ChromeFrameActiveXContainer { | |
783 public: | |
784 ChromeFrameActiveXContainerMemory() | |
785 : delegate_(NULL) {} | |
786 | |
787 ~ChromeFrameActiveXContainerMemory() {} | |
788 | |
789 void Initialize(ChromeFrameMemoryTest* delegate) { | |
790 ASSERT_TRUE(delegate != NULL); | |
791 delegate_ = delegate; | |
792 } | |
793 | |
794 protected: | |
795 virtual void OnLoadCallbackImpl(const VARIANT* param) { | |
796 delegate_->OnNavigationSuccess(param); | |
797 } | |
798 | |
799 virtual void OnLoadErrorCallbackImpl(const VARIANT* param) { | |
800 delegate_->OnNavigationFailure(param); | |
801 } | |
802 | |
803 ChromeFrameMemoryTest* delegate_; | |
804 }; | |
805 | |
806 // This class runs memory tests against the ChromeFrame ActiveX. | |
807 template<class MemoryTestBase> | |
808 class ChromeFrameActiveXMemoryTest : public MemoryTestBase { | |
809 public: | |
810 ChromeFrameActiveXMemoryTest() | |
811 : chrome_frame_container_(NULL), | |
812 test_completed_(false) {} | |
813 | |
814 ~ChromeFrameActiveXMemoryTest() { | |
815 } | |
816 | |
817 void StartTest(const std::string& url, const std::string& test_name) { | |
818 ASSERT_TRUE(chrome_frame_container_ == NULL); | |
819 | |
820 test_name_ = test_name; | |
821 | |
822 SimpleModule module; | |
823 AtlAxWinInit(); | |
824 | |
825 CComObject<ChromeFrameActiveXContainerMemory>::CreateInstance( | |
826 &chrome_frame_container_); | |
827 chrome_frame_container_->AddRef(); | |
828 | |
829 chrome_frame_container_->Initialize(this); | |
830 | |
831 chrome_frame_container_->CreateChromeFrameWindow(url.c_str()); | |
832 chrome_frame_container_->CreateControl(true); | |
833 | |
834 module.RunMessageLoop(); | |
835 | |
836 chrome_frame_container_->Release(); | |
837 | |
838 PrintResults(test_name_.c_str()); | |
839 | |
840 CoFreeUnusedLibraries(); | |
841 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); | |
842 } | |
843 | |
844 void NavigateImpl(const std::string& url) { | |
845 ASSERT_TRUE(chrome_frame_container_ != NULL); | |
846 ASSERT_TRUE(!url.empty()); | |
847 chrome_frame_container_->Navigate(url.c_str()); | |
848 } | |
849 | |
850 void TestCompleted() { | |
851 // This can get called multiple times if the last url results in a | |
852 // redirect. | |
853 if (!test_completed_) { | |
854 // Measure memory usage for the browser process. | |
855 AccountProcessMemoryUsage(chrome_browser_process_id()); | |
856 // Measure memory usage for the current process. | |
857 AccountProcessMemoryUsage(GetCurrentProcessId()); | |
858 | |
859 test_completed_ = true; | |
860 EXPECT_TRUE(PostMessage(static_cast<HWND>(*chrome_frame_container_), | |
861 WM_CLOSE, 0, 0)); | |
862 } | |
863 } | |
864 | |
865 protected: | |
866 CComObject<ChromeFrameActiveXContainerMemory>* chrome_frame_container_; | |
867 std::string test_name_; | |
868 bool test_completed_; | |
869 }; | |
870 | |
871 // This class runs tests to measure chrome frame creation only. This will help | |
872 // track overall page load performance with chrome frame instances. | |
873 class ChromeFrameCreationTest : public ChromeFrameStartupTest { | |
874 protected: | |
875 virtual void RunStartupTestImpl(TimeTicks* start_time, | |
876 TimeTicks* end_time) { | |
877 SimpleModule module; | |
878 AtlAxWinInit(); | |
879 CComObjectStackEx<ChromeFrameActiveXContainer> wnd; | |
880 wnd.CreateChromeFrameWindow(startup_url_); | |
881 *start_time = TimeTicks::Now(); | |
882 wnd.CreateControl(false); | |
883 *end_time = TimeTicks::Now(); | |
884 } | |
885 }; | |
886 | |
887 // This class provides functionality to run the chrome frame | |
888 // performance test against a reference build. | |
889 class ChromeFrameCreationTestReference : public ChromeFrameCreationTest { | |
890 public: | |
891 // override the browser directory to use the reference build instead. | |
892 virtual void SetUp() { | |
893 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar( | |
894 ScopedChromeFrameRegistrar::SYSTEM_LEVEL)); | |
895 chrome_frame_registrar_->RegisterReferenceChromeFrameBuild(); | |
896 ChromeFrameStartupTest::SetUp(); | |
897 } | |
898 | |
899 virtual void TearDown() { | |
900 chrome_frame_registrar_.reset(NULL); | |
901 } | |
902 }; | |
903 | |
904 // This class measures the creation time for Flash, which would be used | |
905 // as a baseline to measure chrome frame creation performance. | |
906 class FlashCreationTest : public ChromeFrameStartupTest { | |
907 protected: | |
908 virtual void RunStartupTestImpl(TimeTicks* start_time, | |
909 TimeTicks* end_time) { | |
910 SimpleModule module; | |
911 AtlAxWinInit(); | |
912 CAxWindow host; | |
913 RECT rc = {0, 0, 800, 600}; | |
914 host.Create(NULL, rc, NULL, | |
915 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, | |
916 WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); | |
917 EXPECT_TRUE(host.m_hWnd != NULL); | |
918 | |
919 *start_time = TimeTicks::Now(); | |
920 HRESULT hr = host.CreateControl(L"ShockwaveFlash.ShockwaveFlash"); | |
921 EXPECT_HRESULT_SUCCEEDED(hr); | |
922 *end_time = TimeTicks::Now(); | |
923 | |
924 ReleaseHostComReferences(host); | |
925 } | |
926 }; | |
927 | |
928 // This class measures the creation time for Silverlight, which would be used | |
929 // as a baseline to measure chrome frame creation performance. | |
930 class SilverlightCreationTest : public ChromeFrameStartupTest { | |
931 protected: | |
932 virtual void RunStartupTestImpl(TimeTicks* start_time, | |
933 TimeTicks* end_time) { | |
934 SimpleModule module; | |
935 AtlAxWinInit(); | |
936 CAxWindow host; | |
937 RECT rc = {0, 0, 800, 600}; | |
938 host.Create(NULL, rc, NULL, | |
939 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, | |
940 WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); | |
941 EXPECT_TRUE(host.m_hWnd != NULL); | |
942 | |
943 *start_time = TimeTicks::Now(); | |
944 HRESULT hr = host.CreateControl(L"AgControl.AgControl"); | |
945 EXPECT_HRESULT_SUCCEEDED(hr); | |
946 *end_time = TimeTicks::Now(); | |
947 | |
948 ReleaseHostComReferences(host); | |
949 } | |
950 }; | |
951 | |
952 // TODO(rogerm): Flesh out the *PreReadImage* tests to validate an observed | |
953 // change in paging behaviour between raw loading and pre-reading. | |
954 | |
955 // TODO(rogerm): Add checks to the *PreReadImage* tests to validate the | |
956 // handling of invalid pe files and paths as input. | |
957 | |
958 TEST(ImagePreReader, PreReadImage) { | |
959 base::FilePath current_exe; | |
960 ASSERT_TRUE(PathService::Get(base::FILE_EXE, ¤t_exe)); | |
961 | |
962 int64 file_size_64 = 0; | |
963 ASSERT_TRUE(base::GetFileSize(current_exe, &file_size_64)); | |
964 ASSERT_TRUE(file_size_64 < std::numeric_limits<std::size_t>::max()); | |
965 size_t file_size = static_cast<size_t>(file_size_64); | |
966 | |
967 const wchar_t* module_path = current_exe.value().c_str(); | |
968 const size_t kStepSize = 2 * 1024 * 1024; | |
969 | |
970 ASSERT_TRUE( | |
971 ImagePreReader::PreReadImage(module_path, 0, kStepSize)); | |
972 ASSERT_TRUE( | |
973 ImagePreReader::PreReadImage(module_path, file_size / 4, kStepSize)); | |
974 ASSERT_TRUE( | |
975 ImagePreReader::PreReadImage(module_path, file_size / 2, kStepSize)); | |
976 ASSERT_TRUE( | |
977 ImagePreReader::PreReadImage(module_path, file_size, kStepSize)); | |
978 ASSERT_TRUE( | |
979 ImagePreReader::PreReadImage(module_path, file_size * 2, kStepSize)); | |
980 } | |
981 | |
982 TEST(ImagePreReader, PartialPreReadImage) { | |
983 base::FilePath current_exe; | |
984 ASSERT_TRUE(PathService::Get(base::FILE_EXE, ¤t_exe)); | |
985 | |
986 const wchar_t* module_path = current_exe.value().c_str(); | |
987 const size_t kStepSize = 2 * 1024 * 1024; | |
988 | |
989 ASSERT_TRUE( | |
990 ImagePreReader::PartialPreReadImage(module_path, 0, kStepSize)); | |
991 ASSERT_TRUE( | |
992 ImagePreReader::PartialPreReadImage(module_path, 25, kStepSize)); | |
993 ASSERT_TRUE( | |
994 ImagePreReader::PartialPreReadImage(module_path, 50, kStepSize)); | |
995 ASSERT_TRUE( | |
996 ImagePreReader::PartialPreReadImage(module_path, 100, kStepSize)); | |
997 ASSERT_TRUE( | |
998 ImagePreReader::PartialPreReadImage(module_path, 150, kStepSize)); | |
999 } | |
1000 | |
1001 TEST(ImagePreReader, PartialPreReadImageOnDisk) { | |
1002 base::FilePath current_exe; | |
1003 ASSERT_TRUE(PathService::Get(base::FILE_EXE, ¤t_exe)); | |
1004 | |
1005 const wchar_t* module_path = current_exe.value().c_str(); | |
1006 const size_t kChunkSize = 2 * 1024 * 1024; | |
1007 | |
1008 ASSERT_TRUE( | |
1009 ImagePreReader::PartialPreReadImageOnDisk(module_path, 0, kChunkSize)); | |
1010 ASSERT_TRUE( | |
1011 ImagePreReader::PartialPreReadImageOnDisk(module_path, 25, kChunkSize)); | |
1012 ASSERT_TRUE( | |
1013 ImagePreReader::PartialPreReadImageOnDisk(module_path, 50, kChunkSize)); | |
1014 ASSERT_TRUE( | |
1015 ImagePreReader::PartialPreReadImageOnDisk(module_path, 100, kChunkSize)); | |
1016 ASSERT_TRUE( | |
1017 ImagePreReader::PartialPreReadImageOnDisk(module_path, 150, kChunkSize)); | |
1018 } | |
1019 | |
1020 TEST(ImagePreReader, PartialPreReadImageInMemory) { | |
1021 base::FilePath current_exe; | |
1022 ASSERT_TRUE(PathService::Get(base::FILE_EXE, ¤t_exe)); | |
1023 const wchar_t* module_path = current_exe.value().c_str(); | |
1024 | |
1025 ASSERT_TRUE( | |
1026 ImagePreReader::PartialPreReadImageInMemory(module_path, 0)); | |
1027 ASSERT_TRUE( | |
1028 ImagePreReader::PartialPreReadImageInMemory(module_path, 25)); | |
1029 ASSERT_TRUE( | |
1030 ImagePreReader::PartialPreReadImageInMemory(module_path, 50)); | |
1031 ASSERT_TRUE( | |
1032 ImagePreReader::PartialPreReadImageInMemory(module_path, 100)); | |
1033 ASSERT_TRUE( | |
1034 ImagePreReader::PartialPreReadImageInMemory(module_path, 150)); | |
1035 } | |
1036 | |
1037 TEST(ChromeFramePerf, DISABLED_HostActiveX) { | |
1038 // TODO(stoyan): Create a low integrity level thread && perform the test there | |
1039 SimpleModule module; | |
1040 AtlAxWinInit(); | |
1041 CComObjectStackEx<ChromeFrameActiveXContainerPerf> wnd; | |
1042 wnd.CreateChromeFrameWindow("http://www.google.com"); | |
1043 wnd.CreateControl(true); | |
1044 module.RunMessageLoop(); | |
1045 } | |
1046 | |
1047 TEST(ChromeFramePerf, DISABLED_HostActiveXInvalidURL) { | |
1048 // TODO(stoyan): Create a low integrity level thread && perform the test there | |
1049 SimpleModule module; | |
1050 AtlAxWinInit(); | |
1051 CComObjectStackEx<ChromeFrameActiveXContainerPerf> wnd; | |
1052 wnd.CreateChromeFrameWindow("http://non-existent-domain.org/"); | |
1053 wnd.CreateControl(true); | |
1054 module.RunMessageLoop(); | |
1055 } | |
1056 | |
1057 TEST_F(ChromeFrameStartupTestActiveX, PerfWarm) { | |
1058 RunStartupTest("warm", "t", "about:blank", false /* cold */, 0, NULL, | |
1059 true /* important */, false); | |
1060 } | |
1061 | |
1062 TEST_F(ChromeFrameBinariesLoadTest, PerfWarm) { | |
1063 RunStartupTest("binary_load_warm", "t", "", false /* cold */, 0, NULL, | |
1064 true /* important */, false); | |
1065 } | |
1066 | |
1067 TEST_F(ChromeFrameStartupTestActiveX, PerfCold) { | |
1068 SetConfigInt(L"PreRead", 0); | |
1069 base::FilePath binaries_to_evict[] = { | |
1070 ffmpegsumo_dll_, chrome_exe_, chrome_dll_, chrome_frame_dll_ | |
1071 }; | |
1072 RunStartupTest("cold", "t", "about:blank", true /* cold */, | |
1073 arraysize(binaries_to_evict), binaries_to_evict, | |
1074 false /* not important */, false); | |
1075 DeleteConfigValue(L"PreRead"); | |
1076 } | |
1077 | |
1078 TEST_F(ChromeFrameStartupTestActiveX, PerfColdPreRead) { | |
1079 SetConfigInt(L"PreRead", 1); | |
1080 base::FilePath binaries_to_evict[] = { | |
1081 ffmpegsumo_dll_, chrome_exe_, chrome_dll_, chrome_frame_dll_ | |
1082 }; | |
1083 RunStartupTest("cold_preread", "t", "about:blank", true /* cold */, | |
1084 arraysize(binaries_to_evict), binaries_to_evict, | |
1085 false /* not important */, false); | |
1086 DeleteConfigValue(L"PreRead"); | |
1087 } | |
1088 | |
1089 TEST_F(ChromeFrameBinariesLoadTest, PerfCold) { | |
1090 base::FilePath binaries_to_evict[] = {chrome_exe_, chrome_dll_}; | |
1091 RunStartupTest("binary_load_cold", "t", "", true /* cold */, | |
1092 arraysize(binaries_to_evict), binaries_to_evict, | |
1093 false /* not important */, false); | |
1094 } | |
1095 | |
1096 TEST_F(ChromeFrameBinariesLoadTest, PerfColdPreRead) { | |
1097 base::FilePath binaries_to_evict[] = {chrome_exe_, chrome_dll_}; | |
1098 pre_read_type_ = kPreReadFull; | |
1099 RunStartupTest("binary_load_cold_preread", "t", "", true /* cold */, | |
1100 arraysize(binaries_to_evict), binaries_to_evict, | |
1101 false /* not important */, false); | |
1102 } | |
1103 | |
1104 TEST_F(ChromeFrameBinariesLoadTest, PerfColdPartialPreRead15) { | |
1105 base::FilePath binaries_to_evict[] = {chrome_exe_, chrome_dll_}; | |
1106 pre_read_type_ = kPreReadPartial; | |
1107 percentage_to_preread_ = 15; | |
1108 RunStartupTest("binary_load_cold_partial_preread", "t", "", true /* cold */, | |
1109 arraysize(binaries_to_evict), binaries_to_evict, | |
1110 false /* not important */, false); | |
1111 } | |
1112 | |
1113 | |
1114 TEST_F(ChromeFrameBinariesLoadTest, PerfColdPartialPreRead25) { | |
1115 base::FilePath binaries_to_evict[] = {chrome_exe_, chrome_dll_}; | |
1116 pre_read_type_ = kPreReadPartial; | |
1117 percentage_to_preread_ = 25; | |
1118 RunStartupTest("binary_load_cold_partial_preread", "t", "", true /* cold */, | |
1119 arraysize(binaries_to_evict), binaries_to_evict, | |
1120 false /* not important */, false); | |
1121 } | |
1122 | |
1123 TEST_F(ChromeFrameBinariesLoadTest, PerfColdPartialPreRead40) { | |
1124 base::FilePath binaries_to_evict[] = {chrome_exe_, chrome_dll_}; | |
1125 pre_read_type_ = kPreReadPartial; | |
1126 percentage_to_preread_ = 40; | |
1127 RunStartupTest("binary_load_cold_partial_preread", "t", "", true /* cold */, | |
1128 arraysize(binaries_to_evict), binaries_to_evict, | |
1129 false /* not important */, false); | |
1130 } | |
1131 | |
1132 TEST_F(ChromeFrameStartupTestActiveXReference, PerfWarm) { | |
1133 RunStartupTest("warm", "t_ref", "about:blank", false /* cold */, 0, NULL, | |
1134 true /* important */, false); | |
1135 } | |
1136 | |
1137 TEST_F(ChromeFrameStartupTestActiveX, PerfChromeFrameInitializationWarm) { | |
1138 RunStartupTest("ChromeFrame_init_warm", "t", "", false /* cold */, 0, | |
1139 NULL, true /* important */, false); | |
1140 } | |
1141 | |
1142 TEST_F(ChromeFrameStartupTestActiveX, PerfChromeFrameInitializationCold) { | |
1143 base::FilePath binaries_to_evict[] = {chrome_frame_dll_}; | |
1144 RunStartupTest("ChromeFrame_init_cold", "t", "", true /* cold */, | |
1145 arraysize(binaries_to_evict), binaries_to_evict, | |
1146 false /* not important */, false); | |
1147 } | |
1148 | |
1149 TEST_F(ChromeFrameStartupTestActiveXReference, | |
1150 PerfChromeFrameInitializationWarm) { | |
1151 RunStartupTest("ChromeFrame_init_warm", "t_ref", "", false /* cold */, 0, | |
1152 NULL, true /* important */, false); | |
1153 } | |
1154 | |
1155 typedef ChromeFrameActiveXMemoryTest<ChromeFrameMemoryTest> | |
1156 RegularChromeFrameActiveXMemoryTest; | |
1157 | |
1158 TEST_F(RegularChromeFrameActiveXMemoryTest, MemoryTestAboutBlank) { | |
1159 char *urls[] = {"about:blank"}; | |
1160 RunTest("memory_about_blank", urls, arraysize(urls)); | |
1161 } | |
1162 | |
1163 // TODO(iyengar) | |
1164 // Revisit why the chrome frame dll does not unload correctly when this test is | |
1165 // run. | |
1166 // http://code.google.com/p/chromium/issues/detail?id=47812 | |
1167 TEST_F(RegularChromeFrameActiveXMemoryTest, DISABLED_MemoryTestUrls) { | |
1168 // TODO(iyengar) | |
1169 // We should use static pages to measure memory usage. | |
1170 char *urls[] = { | |
1171 "http://www.youtube.com/watch?v=PN2HAroA12w", | |
1172 "http://www.youtube.com/watch?v=KmLJDrsaJmk&feature=channel" | |
1173 }; | |
1174 | |
1175 RunTest("memory", urls, arraysize(urls)); | |
1176 } | |
1177 | |
1178 typedef ChromeFrameActiveXMemoryTest<ChromeFrameMemoryTestReference> | |
1179 ReferenceBuildChromeFrameActiveXMemoryTest; | |
1180 | |
1181 // Disabled to investigate why the chrome frame dll does not unload while | |
1182 // running this test. | |
1183 // http://code.google.com/p/chromium/issues/detail?id=47812 | |
1184 TEST_F(ReferenceBuildChromeFrameActiveXMemoryTest, | |
1185 DISABLED_MemoryTestAboutBlank) { | |
1186 char *urls[] = {"about:blank"}; | |
1187 RunTest("memory_about_blank_reference", urls, arraysize(urls)); | |
1188 } | |
1189 | |
1190 // TODO(iyengar) | |
1191 // Revisit why the chrome frame dll does not unload correctly when this test is | |
1192 // run. | |
1193 TEST_F(ReferenceBuildChromeFrameActiveXMemoryTest, DISABLED_MemoryTestUrls) { | |
1194 // TODO(iyengar) | |
1195 // We should use static pages to measure memory usage. | |
1196 char *urls[] = { | |
1197 "http://www.youtube.com/watch?v=PN2HAroA12w", | |
1198 "http://www.youtube.com/watch?v=KmLJDrsaJmk&feature=channel" | |
1199 }; | |
1200 | |
1201 RunTest("memory_reference", urls, arraysize(urls)); | |
1202 } | |
1203 | |
1204 TEST_F(ChromeFrameCreationTest, PerfWarm) { | |
1205 RunStartupTest("creation_warm", "t", "", false /* cold */, 0, | |
1206 NULL, true /* important */, false); | |
1207 } | |
1208 | |
1209 TEST_F(ChromeFrameCreationTestReference, PerfWarm) { | |
1210 RunStartupTest("creation_warm", "t_ref", "about:blank", false /* cold */, 0, | |
1211 NULL, true /* not important */, false); | |
1212 } | |
1213 | |
1214 TEST_F(FlashCreationTest, DISABLED_PerfWarm) { | |
1215 RunStartupTest("creation_warm", "t_flash", "", false /* cold */, 0, NULL, | |
1216 true /* not important */, false); | |
1217 } | |
1218 | |
1219 TEST_F(SilverlightCreationTest, DISABLED_PerfWarm) { | |
1220 RunStartupTest("creation_warm", "t_silverlight", "", false /* cold */, 0, | |
1221 NULL, false /* not important */, false); | |
1222 } | |
1223 | |
1224 TEST_F(ChromeFrameCreationTest, PerfCold) { | |
1225 base::FilePath binaries_to_evict[] = {chrome_frame_dll_}; | |
1226 | |
1227 RunStartupTest("creation_cold", "t", "", true /* cold */, | |
1228 arraysize(binaries_to_evict), binaries_to_evict, | |
1229 true /* important */, false); | |
1230 } | |
1231 | |
1232 // Attempt to evict the Flash control can fail on the buildbot as the dll | |
1233 // is marked read only. The test run is aborted if we fail to evict the file | |
1234 // from the cache. This could also fail if the Flash control is in use. | |
1235 // On Vista this could fail because of UAC | |
1236 TEST_F(FlashCreationTest, PerfCold) { | |
1237 base::win::RegKey flash_key(HKEY_CLASSES_ROOT, kFlashControlKey, KEY_READ); | |
1238 | |
1239 std::wstring plugin_path; | |
1240 ASSERT_EQ(ERROR_SUCCESS, flash_key.ReadValue(L"", &plugin_path)); | |
1241 ASSERT_FALSE(plugin_path.empty()); | |
1242 | |
1243 base::FilePath flash_path = base::FilePath(plugin_path); | |
1244 base::FilePath binaries_to_evict[] = {flash_path}; | |
1245 | |
1246 RunStartupTest("creation_cold", "t_flash", "", true /* cold */, | |
1247 arraysize(binaries_to_evict), binaries_to_evict, | |
1248 false/* important */, true); | |
1249 } | |
1250 | |
1251 // This test would fail on Vista due to UAC or if the Silverlight control is | |
1252 // in use. The test run is aborted if we fail to evict the file from the cache. | |
1253 // Disabling this test as the Silverlight dll does not seem to get unloaded | |
1254 // correctly causing the attempt to evict the dll from the system cache to | |
1255 // fail. | |
1256 TEST_F(SilverlightCreationTest, DISABLED_PerfCold) { | |
1257 base::win::RegKey silverlight_key(HKEY_CLASSES_ROOT, kSilverlightControlKey, | |
1258 KEY_READ); | |
1259 | |
1260 std::wstring plugin_path; | |
1261 ASSERT_EQ(ERROR_SUCCESS, silverlight_key.ReadValue(L"", &plugin_path)); | |
1262 ASSERT_FALSE(plugin_path.empty()); | |
1263 | |
1264 base::FilePath silverlight_path = base::FilePath(plugin_path); | |
1265 base::FilePath binaries_to_evict[] = {silverlight_path}; | |
1266 | |
1267 RunStartupTest("creation_cold", "t_silverlight", "", true /* cold */, | |
1268 arraysize(binaries_to_evict), binaries_to_evict, | |
1269 false /* important */, true); | |
1270 } | |
1271 | |
1272 namespace { | |
1273 | |
1274 // Derive from this class in order to receive custom events traced | |
1275 // via TRACE_EVENT_XXXX macros from ChromeFrame/Chrome. | |
1276 class TracedEvents { | |
1277 public: | |
1278 virtual void OnTraceEventBegin(EVENT_TRACE* event) {} | |
1279 virtual void OnTraceEventEnd(EVENT_TRACE* event) {} | |
1280 virtual void OnTraceEventInstant(EVENT_TRACE* event) {} | |
1281 }; | |
1282 | |
1283 // For the time being we pass to delegate only base::kTraceEventClass32 | |
1284 // events i.e. these generated by TRACE_EVENT_XXXX macros. | |
1285 // We may need to add kernel provider and pass Process Start/Exit events etc, | |
1286 // but for the time being we stick with base::kChromeTraceProviderName | |
1287 // provider only. | |
1288 class EtwConsumer : public base::win::EtwTraceConsumerBase<EtwConsumer> { | |
1289 public: | |
1290 EtwConsumer() { | |
1291 set_delegate(NULL); | |
1292 } | |
1293 | |
1294 ~EtwConsumer() { | |
1295 set_delegate(NULL); | |
1296 } | |
1297 | |
1298 void set_delegate(TracedEvents* delegate) { | |
1299 delegate_ = delegate; | |
1300 } | |
1301 | |
1302 static void ProcessEvent(EVENT_TRACE* event) { | |
1303 DCHECK(delegate_); | |
1304 if (event->Header.Guid != base::debug::kTraceEventClass32) | |
1305 return; | |
1306 if (event->Header.Class.Version != 0) | |
1307 return; | |
1308 | |
1309 switch (event->Header.Class.Type) { | |
1310 case base::debug::kTraceEventTypeBegin: | |
1311 delegate_->OnTraceEventBegin(event); | |
1312 break; | |
1313 case base::debug::kTraceEventTypeEnd: | |
1314 delegate_->OnTraceEventEnd(event); | |
1315 break; | |
1316 case base::debug::kTraceEventTypeInstant: | |
1317 delegate_->OnTraceEventInstant(event); | |
1318 break; | |
1319 default: | |
1320 NOTREACHED(); | |
1321 break; | |
1322 } | |
1323 } | |
1324 | |
1325 static TracedEvents* delegate_; | |
1326 }; | |
1327 | |
1328 TracedEvents* EtwConsumer::delegate_ = NULL; | |
1329 }; // namespace | |
1330 | |
1331 class EtwPerfSession { | |
1332 public: | |
1333 EtwPerfSession() { | |
1334 } | |
1335 | |
1336 ~EtwPerfSession() { | |
1337 base::DeleteFile(etl_log_file_, false); | |
1338 } | |
1339 | |
1340 void Start() { | |
1341 // To ensure there is no session leftover from crashes, previous runs, etc. | |
1342 base::win::EtwTraceProperties ignore; | |
1343 base::win::EtwTraceController::Stop(L"cf_perf", &ignore); | |
1344 ASSERT_TRUE(base::CreateTemporaryFile(&etl_log_file_)); | |
1345 ASSERT_HRESULT_SUCCEEDED(controller_.StartFileSession(L"cf_perf", | |
1346 etl_log_file_.value().c_str(), false)); | |
1347 ASSERT_HRESULT_SUCCEEDED(controller_.EnableProvider( | |
1348 base::debug::kChromeTraceProviderName, | |
1349 TRACE_LEVEL_INFORMATION, | |
1350 ~(base::debug::CAPTURE_STACK_TRACE))); | |
1351 } | |
1352 | |
1353 HRESULT Stop() { | |
1354 return controller_.Stop(NULL); | |
1355 } | |
1356 | |
1357 void AnalyzeOutput(TracedEvents* delegate) { | |
1358 EtwConsumer consumer; | |
1359 consumer.set_delegate(delegate); | |
1360 consumer.OpenFileSession(etl_log_file_.value().c_str()); | |
1361 consumer.Consume(); | |
1362 consumer.Close(); | |
1363 } | |
1364 | |
1365 base::FilePath etl_log_file_; | |
1366 base::win::EtwTraceController controller_; | |
1367 }; | |
1368 | |
1369 // Base class for the tracing event helper classes. | |
1370 class MonitorTraceBase { | |
1371 public: | |
1372 static bool IsMatchingEvent(EVENT_TRACE* event, | |
1373 const base::StringPiece& event_to_compare) { | |
1374 return event->MofLength > event_to_compare.size() && | |
1375 (memcmp(event_to_compare.data(), event->MofData, | |
1376 event_to_compare.size() + 1) == 0); | |
1377 } | |
1378 | |
1379 bool is_valid() const { | |
1380 return !start_.is_null() && !end_.is_null() && start_ <= end_; | |
1381 } | |
1382 | |
1383 base::TimeDelta duration() const { | |
1384 return end_ - start_; | |
1385 } | |
1386 | |
1387 base::Time start_; | |
1388 base::Time end_; | |
1389 }; | |
1390 | |
1391 // This class measures the time between begin and end events of a particular | |
1392 // type. | |
1393 class MonitorTracePair : public MonitorTraceBase, | |
1394 public TracedEvents { | |
1395 public: | |
1396 MonitorTracePair() : event_(NULL) { | |
1397 } | |
1398 | |
1399 void set_interesting_event(const char* event) { | |
1400 event_ = event; | |
1401 } | |
1402 | |
1403 virtual void OnTraceEventBegin(EVENT_TRACE* event) { | |
1404 if (IsMatchingEvent(event, event_)) { | |
1405 EXPECT_TRUE(start_.is_null()); | |
1406 start_ = base::Time::FromFileTime( | |
1407 reinterpret_cast<FILETIME&>(event->Header.TimeStamp)); | |
1408 } | |
1409 } | |
1410 | |
1411 virtual void OnTraceEventEnd(EVENT_TRACE* event) { | |
1412 if (IsMatchingEvent(event, event_)) { | |
1413 EXPECT_FALSE(start_.is_null()); | |
1414 EXPECT_TRUE(end_.is_null()); | |
1415 end_ = base::Time::FromFileTime( | |
1416 reinterpret_cast<FILETIME&>(event->Header.TimeStamp)); | |
1417 } | |
1418 } | |
1419 | |
1420 base::StringPiece event_; | |
1421 }; | |
1422 | |
1423 // This class measures the time between two events. | |
1424 class MonitorTraceBetweenEventPair : public MonitorTraceBase, | |
1425 public TracedEvents { | |
1426 public: | |
1427 MonitorTraceBetweenEventPair() : event_end_(NULL), | |
1428 event_start_(NULL) { | |
1429 } | |
1430 | |
1431 void set_start_event(const char* event) { | |
1432 event_start_ = event; | |
1433 } | |
1434 | |
1435 void set_end_event(const char* event) { | |
1436 event_end_ = event; | |
1437 } | |
1438 | |
1439 virtual void OnTraceEventBegin(EVENT_TRACE* event) { | |
1440 if (IsMatchingEvent(event, event_start_)) { | |
1441 EXPECT_TRUE(start_.is_null()); | |
1442 EXPECT_TRUE(end_.is_null()); | |
1443 start_ = base::Time::FromFileTime( | |
1444 reinterpret_cast<FILETIME&>(event->Header.TimeStamp)); | |
1445 } else if (IsMatchingEvent(event, event_end_)) { | |
1446 EXPECT_FALSE(start_.is_null()); | |
1447 EXPECT_TRUE(end_.is_null()); | |
1448 end_ = base::Time::FromFileTime( | |
1449 reinterpret_cast<FILETIME&>(event->Header.TimeStamp)); | |
1450 } | |
1451 } | |
1452 | |
1453 virtual void OnTraceEventEnd(EVENT_TRACE* event) {} | |
1454 | |
1455 base::StringPiece event_start_; | |
1456 base::StringPiece event_end_; | |
1457 }; | |
1458 | |
1459 // The very same as UIPerfTest::PrintResultXXXX without the need to | |
1460 // create an UIPerfTest instance. | |
1461 void PrintResultsImpl(const std::string& measurement, | |
1462 const std::string& modifier, | |
1463 const std::string& trace, | |
1464 const std::string& values, | |
1465 const std::string& prefix, | |
1466 const std::string& suffix, | |
1467 const std::string& units, | |
1468 bool important) { | |
1469 // <*>RESULT <graph_name>: <trace_name>= <value> <units> | |
1470 // <*>RESULT <graph_name>: <trace_name>= {<mean>, <std deviation>} <units> | |
1471 // <*>RESULT <graph_name>: <trace_name>= [<value>,value,value,...,] <units> | |
1472 printf("%sRESULT %s%s: %s= %s%s%s %s\n", | |
1473 important ? "*" : "", measurement.c_str(), modifier.c_str(), | |
1474 trace.c_str(), prefix.c_str(), values.c_str(), suffix.c_str(), | |
1475 units.c_str()); | |
1476 } | |
1477 | |
1478 void PrintResultList(const std::string& measurement, | |
1479 const std::string& modifier, | |
1480 const std::string& trace, | |
1481 const std::string& values, | |
1482 const std::string& units, | |
1483 bool important) { | |
1484 PrintResultsImpl(measurement, modifier, trace, values, | |
1485 "[", "]", units, important); | |
1486 } | |
1487 | |
1488 bool RunSingleTestOutOfProc(const std::string& test_name) { | |
1489 base::FilePath path; | |
1490 if (!PathService::Get(base::DIR_EXE, &path)) | |
1491 return false; | |
1492 path = path.Append(L"chrome_frame_tests.exe"); | |
1493 | |
1494 CommandLine cmd_line(path); | |
1495 // Always enable disabled tests. This method is not called with disabled | |
1496 // tests unless this flag was specified to the browser test executable. | |
1497 cmd_line.AppendSwitch("gtest_also_run_disabled_tests"); | |
1498 cmd_line.AppendSwitchASCII("gtest_filter", test_name); | |
1499 | |
1500 base::ProcessHandle process_handle; | |
1501 if (!base::LaunchProcess(cmd_line, base::LaunchOptions(), &process_handle)) | |
1502 return false; | |
1503 | |
1504 base::TimeDelta test_terminate_timeout = base::TimeDelta::FromMinutes(1); | |
1505 int exit_code = 0; | |
1506 if (!base::WaitForExitCodeWithTimeout(process_handle, &exit_code, | |
1507 test_terminate_timeout)) { | |
1508 LOG(ERROR) << "Test timeout (" << test_terminate_timeout.InMilliseconds() | |
1509 << " ms) exceeded for " << test_name; | |
1510 | |
1511 exit_code = -1; // Set a non-zero exit code to signal a failure. | |
1512 | |
1513 // Ensure that the process terminates. | |
1514 base::KillProcess(process_handle, -1, true); | |
1515 } | |
1516 | |
1517 base::CloseProcessHandle(process_handle); | |
1518 | |
1519 return exit_code == 0; | |
1520 } | |
1521 | |
1522 template <class Monitor> | |
1523 void PrintPerfTestResults(const Monitor* monitor, | |
1524 int num_cycles, | |
1525 const char* result_name) { | |
1526 std::string times; | |
1527 | |
1528 for (int i = 0; i < num_cycles; ++i) { | |
1529 ASSERT_TRUE(monitor[i].is_valid()); | |
1530 base::StringAppendF(×, | |
1531 "%.2f,", | |
1532 monitor[i].duration().InMillisecondsF()); | |
1533 } | |
1534 | |
1535 PrintResultList(result_name, "", "t", times, "ms", false); | |
1536 } | |
1537 | |
1538 TEST(TestAsPerfTest, MetaTag_createproxy) { | |
1539 const int kNumCycles = 10; | |
1540 | |
1541 MonitorTracePair create_proxy_monitor[kNumCycles]; | |
1542 MonitorTraceBetweenEventPair browser_main_start_monitor[kNumCycles]; | |
1543 MonitorTraceBetweenEventPair browser_main_loop_monitor[kNumCycles]; | |
1544 MonitorTraceBetweenEventPair automation_provider_start_monitor[kNumCycles]; | |
1545 MonitorTraceBetweenEventPair automation_provider_connect_monitor[kNumCycles]; | |
1546 MonitorTracePair external_tab_navigate_monitor[kNumCycles]; | |
1547 MonitorTracePair pre_read_chrome_monitor[kNumCycles]; | |
1548 MonitorTraceBetweenEventPair renderer_main_monitor[kNumCycles]; | |
1549 | |
1550 for (int i = 0; i < kNumCycles; ++i) { | |
1551 EtwPerfSession perf_session; | |
1552 ASSERT_NO_FATAL_FAILURE(perf_session.Start()); | |
1553 ASSERT_TRUE(RunSingleTestOutOfProc( | |
1554 "ChromeFrameTestWithWebServer.FullTabModeIE_MetaTag")); | |
1555 // Since we cannot have array of objects with a non-default constructor, | |
1556 // dedicated method is used to initialize watched event. | |
1557 create_proxy_monitor[i].set_interesting_event("chromeframe.createproxy"); | |
1558 | |
1559 browser_main_start_monitor[i].set_start_event("chromeframe.createproxy"); | |
1560 browser_main_start_monitor[i].set_end_event("BrowserMain"); | |
1561 | |
1562 browser_main_loop_monitor[i].set_start_event("BrowserMain"); | |
1563 browser_main_loop_monitor[i].set_end_event("BrowserMain:MESSAGE_LOOP"); | |
1564 | |
1565 automation_provider_start_monitor[i].set_start_event("BrowserMain"); | |
1566 automation_provider_start_monitor[i].set_end_event( | |
1567 "AutomationProvider::AutomationProvider"); | |
1568 | |
1569 automation_provider_connect_monitor[i].set_start_event( | |
1570 "AutomationProvider::AutomationProvider"); | |
1571 automation_provider_connect_monitor[i].set_end_event( | |
1572 "AutomationProvider::InitializeChannel"); | |
1573 | |
1574 external_tab_navigate_monitor[i].set_interesting_event( | |
1575 "ExternalTabContainerWin::Navigate"); | |
1576 | |
1577 renderer_main_monitor[i].set_start_event( | |
1578 "ExternalTabContainerWin::Navigate"); | |
1579 renderer_main_monitor[i].set_end_event("RendererMain"); | |
1580 | |
1581 pre_read_chrome_monitor[i].set_interesting_event("PreReadImage"); | |
1582 | |
1583 ASSERT_HRESULT_SUCCEEDED(perf_session.Stop()); | |
1584 | |
1585 perf_session.AnalyzeOutput(&create_proxy_monitor[i]); | |
1586 perf_session.AnalyzeOutput(&browser_main_start_monitor[i]); | |
1587 perf_session.AnalyzeOutput(&browser_main_loop_monitor[i]); | |
1588 perf_session.AnalyzeOutput(&automation_provider_start_monitor[i]); | |
1589 perf_session.AnalyzeOutput(&automation_provider_connect_monitor[i]); | |
1590 perf_session.AnalyzeOutput(&external_tab_navigate_monitor[i]); | |
1591 perf_session.AnalyzeOutput(&pre_read_chrome_monitor[i]); | |
1592 perf_session.AnalyzeOutput(&renderer_main_monitor[i]); | |
1593 } | |
1594 | |
1595 // Print results | |
1596 PrintPerfTestResults(create_proxy_monitor, kNumCycles, "createproxy"); | |
1597 PrintPerfTestResults(browser_main_start_monitor, kNumCycles, | |
1598 "browserstart"); | |
1599 PrintPerfTestResults(browser_main_loop_monitor, kNumCycles, | |
1600 "browserloop"); | |
1601 PrintPerfTestResults(automation_provider_start_monitor, kNumCycles, | |
1602 "automationproviderstart"); | |
1603 PrintPerfTestResults(automation_provider_connect_monitor, kNumCycles, | |
1604 "automationproviderconnect"); | |
1605 PrintPerfTestResults(external_tab_navigate_monitor, kNumCycles, | |
1606 "externaltabnavigate"); | |
1607 PrintPerfTestResults(renderer_main_monitor, kNumCycles, | |
1608 "beginrenderermain"); | |
1609 #ifdef NDEBUG | |
1610 PrintPerfTestResults(pre_read_chrome_monitor, kNumCycles, "PreReadImage"); | |
1611 #endif // NDEBUG | |
1612 } | |
OLD | NEW |