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

Side by Side Diff: chrome_frame/test/perf/chrome_frame_perftest.cc

Issue 218019: Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 3 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2006-2009 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 #include "chrome_frame/test/perf/chrome_frame_perftest.h"
5
6 #include <atlwin.h>
7 #include <atlhost.h>
8 #include <map>
9 #include <vector>
10 #include <string>
11
12 #include "chrome_tab.h" // Generated from chrome_tab.idl.
13
14 #include "base/file_util.h"
15 #include "base/registry.h"
16 #include "base/scoped_ptr.h"
17 #include "base/scoped_bstr_win.h"
18 #include "base/scoped_comptr_win.h"
19 #include "base/string_util.h"
20 #include "base/time.h"
21 #include "chrome/common/chrome_constants.h"
22 #include "chrome/common/chrome_paths.h"
23 #include "chrome/test/chrome_process_util.h"
24 #include "chrome/test/perf/mem_usage.h"
25 #include "chrome/test/ui/ui_test.h"
26
27 #include "chrome_frame/test_utils.h"
28 #include "chrome_frame/utils.h"
29
30 const wchar_t kSilverlightControlKey[] =
31 L"CLSID\\{DFEAF541-F3E1-4c24-ACAC-99C30715084A}\\InprocServer32";
32
33 const wchar_t kFlashControlKey[] =
34 L"CLSID\\{D27CDB6E-AE6D-11cf-96B8-444553540000}\\InprocServer32";
35
36 using base::TimeDelta;
37 using base::TimeTicks;
38
39 // Callback description for onload, onloaderror, onmessage
40 static _ATL_FUNC_INFO g_single_param = {CC_STDCALL, VT_EMPTY, 1, {VT_VARIANT}};
41 // Simple class that forwards the callbacks.
42 template <typename T>
43 class DispCallback
44 : public IDispEventSimpleImpl<1, DispCallback<T>, &IID_IDispatch> {
45 public:
46 typedef HRESULT (T::*Method)(VARIANT* param);
47
48 DispCallback(T* owner, Method method) : owner_(owner), method_(method) {
49 }
50
51 BEGIN_SINK_MAP(DispCallback)
52 SINK_ENTRY_INFO(1, IID_IDispatch, DISPID_VALUE, OnCallback, &g_single_param)
53 END_SINK_MAP()
54
55 virtual ULONG STDMETHODCALLTYPE AddRef() {
56 return owner_->AddRef();
57 }
58 virtual ULONG STDMETHODCALLTYPE Release() {
59 return owner_->Release();
60 }
61
62 STDMETHOD(OnCallback)(VARIANT param) {
63 return (owner_->*method_)(&param);
64 }
65
66 IDispatch* ToDispatch() {
67 return reinterpret_cast<IDispatch*>(this);
68 }
69
70 T* owner_;
71 Method method_;
72 };
73
74 // This class implements an ActiveX container which hosts the ChromeFrame
75 // ActiveX control. It provides hooks which can be implemented by derived
76 // classes for implementing performance measurement, etc.
77 class ChromeFrameActiveXContainer
78 : public CWindowImpl<ChromeFrameActiveXContainer, CWindow, CWinTraits <
79 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
80 WS_EX_APPWINDOW | WS_EX_WINDOWEDGE> >,
81 public CComObjectRootEx<CComSingleThreadModel>,
82 public IPropertyNotifySink {
83 public:
84 ~ChromeFrameActiveXContainer() {
85 if (m_hWnd)
86 DestroyWindow();
87 }
88
89 DECLARE_WND_CLASS_EX(L"ChromeFrameActiveX_container", 0, 0)
90
91 BEGIN_COM_MAP(ChromeFrameActiveXContainer)
92 COM_INTERFACE_ENTRY(IPropertyNotifySink)
93 END_COM_MAP()
94
95 BEGIN_MSG_MAP(ChromeFrameActiveXContainer)
96 MESSAGE_HANDLER(WM_CREATE, OnCreate)
97 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
98 END_MSG_MAP()
99
100 HRESULT OnMessageCallback(VARIANT* param) {
101 DLOG(INFO) << __FUNCTION__;
102 OnMessageCallbackImpl(param);
103 return S_OK;
104 }
105
106 HRESULT OnLoadErrorCallback(VARIANT* param) {
107 DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal;
108 OnLoadErrorCallbackImpl(param);
109 return S_OK;
110 }
111
112 HRESULT OnLoadCallback(VARIANT* param) {
113 DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal;
114 OnLoadCallbackImpl(param);
115 return S_OK;
116 }
117
118 ChromeFrameActiveXContainer() :
119 prop_notify_cookie_(0),
120 onmsg_(this, &ChromeFrameActiveXContainer::OnMessageCallback),
121 onloaderror_(this, &ChromeFrameActiveXContainer::OnLoadErrorCallback),
122 onload_(this, &ChromeFrameActiveXContainer::OnLoadCallback) {
123 }
124
125 LRESULT OnCreate(UINT , WPARAM , LPARAM , BOOL& ) {
126 chromeview_.Attach(m_hWnd);
127 return 0;
128 }
129
130 // This will be called twice.
131 // Once from CAxHostWindow::OnDestroy (through DefWindowProc)
132 // and once more from the ATL since CAxHostWindow::OnDestroy claims the
133 // message is not handled.
134 LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& handled) { // NOLINT
135 if (prop_notify_cookie_) {
136 AtlUnadvise(tab_, IID_IPropertyNotifySink, prop_notify_cookie_);
137 prop_notify_cookie_ = 0;
138 }
139
140 tab_.Release();
141 return 0;
142 }
143
144 virtual void OnFinalMessage(HWND /*hWnd*/) {
145 ::PostQuitMessage(6);
146 }
147
148 static const wchar_t* GetWndCaption() {
149 return L"ChromeFrame Container";
150 }
151
152 // IPropertyNotifySink
153 STDMETHOD(OnRequestEdit)(DISPID disp_id) {
154 OnRequestEditImpl(disp_id);
155 return S_OK;
156 }
157
158 STDMETHOD(OnChanged)(DISPID disp_id) {
159 if (disp_id != DISPID_READYSTATE)
160 return S_OK;
161
162 long ready_state;
163 HRESULT hr = tab_->get_readyState(&ready_state);
164 DCHECK(hr == S_OK);
165
166 OnReadyStateChanged(ready_state);
167
168 if (ready_state == READYSTATE_COMPLETE) {
169 if(!starting_url_.empty()) {
170 Navigate(starting_url_.c_str());
171 } else {
172 PostMessage(WM_CLOSE);
173 }
174 } else if (ready_state == READYSTATE_UNINITIALIZED) {
175 DLOG(ERROR) << __FUNCTION__ << " Chrome launch failed.";
176 }
177
178 return S_OK;
179 }
180
181 void CreateChromeFrameWindow(const std::string& starting_url) {
182 starting_url_ = starting_url;
183 RECT rc = { 0, 0, 800, 600 };
184 Create(NULL, rc);
185 DCHECK(m_hWnd);
186 ShowWindow(SW_SHOWDEFAULT);
187 }
188
189 void CreateControl(bool setup_event_sinks) {
190 HRESULT hr = chromeview_.CreateControl(L"ChromeTab.ChromeFrame");
191 EXPECT_HRESULT_SUCCEEDED(hr);
192 hr = chromeview_.QueryControl(tab_.Receive());
193 EXPECT_HRESULT_SUCCEEDED(hr);
194
195 if (setup_event_sinks)
196 SetupEventSinks();
197 }
198
199 void Navigate(const char* url) {
200 BeforeNavigateImpl(url);
201
202 HRESULT hr = tab_->put_src(ScopedBstr(UTF8ToWide(url).c_str()));
203 DCHECK(hr == S_OK) << "Chrome frame NavigateToURL(" << url
204 << StringPrintf(L") failed 0x%08X", hr);
205 }
206
207 void SetupEventSinks() {
208 HRESULT hr = AtlAdvise(tab_, this, IID_IPropertyNotifySink,
209 &prop_notify_cookie_);
210 DCHECK(hr == S_OK) << "AtlAdvice for IPropertyNotifySink failed " << hr;
211
212 CComVariant onmessage(onmsg_.ToDispatch());
213 CComVariant onloaderror(onloaderror_.ToDispatch());
214 CComVariant onload(onload_.ToDispatch());
215 EXPECT_HRESULT_SUCCEEDED(tab_->put_onmessage(onmessage));
216 EXPECT_HRESULT_SUCCEEDED(tab_->put_onloaderror(onloaderror));
217 EXPECT_HRESULT_SUCCEEDED(tab_->put_onload(onload));
218 }
219
220 protected:
221 // These functions are implemented by derived classes for special behavior
222 // like performance measurement, etc.
223 virtual void OnReadyStateChanged(long ready_state) {}
224 virtual void OnRequestEditImpl(DISPID disp_id) {}
225
226 virtual void OnMessageCallbackImpl(VARIANT* param) {}
227
228 virtual void OnLoadCallbackImpl(VARIANT* param) {
229 PostMessage(WM_CLOSE);
230 }
231
232 virtual void OnLoadErrorCallbackImpl(VARIANT* param) {
233 PostMessage(WM_CLOSE);
234 }
235 virtual void BeforeNavigateImpl(const char* url) {}
236
237 CAxWindow chromeview_;
238 ScopedComPtr<IChromeFrame> tab_;
239 DWORD prop_notify_cookie_;
240 DispCallback<ChromeFrameActiveXContainer> onmsg_;
241 DispCallback<ChromeFrameActiveXContainer> onloaderror_;
242 DispCallback<ChromeFrameActiveXContainer> onload_;
243 std::string starting_url_;
244 };
245
246 // This class overrides the hooks provided by the ChromeFrameActiveXContainer
247 // class and measures performance at various stages, like initialzation of
248 // the Chrome frame widget, navigation, etc.
249 class ChromeFrameActiveXContainerPerf : public ChromeFrameActiveXContainer {
250 public:
251 ChromeFrameActiveXContainerPerf() {}
252
253 void CreateControl(bool setup_event_sinks) {
254 perf_initialize_.reset(new PerfTimeLogger("Fully initialized"));
255 PerfTimeLogger perf_create("Create Control");
256
257 HRESULT hr = chromeview_.CreateControl(L"ChromeTab.ChromeFrame");
258 EXPECT_HRESULT_SUCCEEDED(hr);
259 hr = chromeview_.QueryControl(tab_.Receive());
260 EXPECT_HRESULT_SUCCEEDED(hr);
261
262 perf_create.Done();
263 if (setup_event_sinks)
264 SetupEventSinks();
265 }
266
267 protected:
268 virtual void OnReadyStateChanged(long ready_state) {
269 // READYSTATE_COMPLETE is fired when the automation server is ready.
270 if (ready_state == READYSTATE_COMPLETE) {
271 perf_initialize_->Done();
272 } else if (ready_state == READYSTATE_INTERACTIVE) {
273 // Window ready. Currently we never receive this notification because it
274 // is fired before we finish setting up our hosting environment.
275 // This is because of how ATL is written. Moving forward we might
276 // have our own hosting classes and then have more control over when we
277 // set up the prop notify sink.
278 } else {
279 DCHECK(ready_state != READYSTATE_UNINITIALIZED) << "failed to initialize";
280 }
281 }
282
283 virtual void OnLoadCallbackImpl(VARIANT* param) {
284 PostMessage(WM_CLOSE);
285 perf_navigate_->Done();
286 }
287
288 virtual void OnLoadErrorCallbackImpl(VARIANT* param) {
289 PostMessage(WM_CLOSE);
290 perf_navigate_->Done();
291 }
292
293 virtual void BeforeNavigateImpl(const char* url ) {
294 std::string test_name = "Navigate ";
295 test_name += url;
296 perf_navigate_.reset(new PerfTimeLogger(test_name.c_str()));
297 }
298
299 scoped_ptr<PerfTimeLogger> perf_initialize_;
300 scoped_ptr<PerfTimeLogger> perf_navigate_;
301 };
302
303 // This class provides common functionality which can be used for most of the
304 // ChromeFrame/Tab performance tests.
305 class ChromeFramePerfTestBase : public UITest {
306 public:
307 ChromeFramePerfTestBase() {}
308 protected:
309 scoped_ptr<ScopedChromeFrameRegistrar> chrome_frame_registrar_;
310 };
311
312 class ChromeFrameStartupTest : public ChromeFramePerfTestBase {
313 public:
314 ChromeFrameStartupTest() {}
315
316 virtual void SetUp() {
317 ASSERT_TRUE(PathService::Get(chrome::DIR_APP, &dir_app_));
318
319 chrome_dll_ = dir_app_.Append(FILE_PATH_LITERAL("chrome.dll"));
320 chrome_exe_ = dir_app_.Append(
321 FilePath::FromWStringHack(chrome::kBrowserProcessExecutableName));
322 chrome_frame_dll_ = dir_app_.Append(
323 FILE_PATH_LITERAL("servers\\npchrome_tab.dll"));
324 }
325 virtual void TearDown() {}
326
327 // TODO(iyengar)
328 // This function is similar to the RunStartupTest function used in chrome
329 // startup tests. Refactor into a common implementation.
330 void RunStartupTest(const char* graph, const char* trace,
331 const char* startup_url, bool test_cold,
332 int total_binaries, const FilePath binaries_to_evict[],
333 bool important, bool ignore_cache_error) {
334 const int kNumCycles = 20;
335
336 startup_url_ = startup_url;
337
338 TimeDelta timings[kNumCycles];
339
340 for (int i = 0; i < kNumCycles; ++i) {
341 if (test_cold) {
342 for (int binary_index = 0; binary_index < total_binaries;
343 binary_index++) {
344 bool result = EvictFileFromSystemCacheWrapper(
345 binaries_to_evict[binary_index]);
346 if (!ignore_cache_error) {
347 ASSERT_TRUE(result);
348 } else if (!result) {
349 printf("\nFailed to evict file %ls from cache. Not running test\n",
350 binaries_to_evict[binary_index].value().c_str());
351 return;
352 }
353 }
354 }
355
356 TimeTicks start_time, end_time;
357
358 RunStartupTestImpl(&start_time, &end_time);
359
360 timings[i] = end_time - start_time;
361
362 CoFreeUnusedLibraries();
363 ASSERT_TRUE(GetModuleHandle(L"npchrome_tab.dll") == NULL);
364
365 // TODO(beng): Can't shut down so quickly. Figure out why, and fix. If we
366 // do, we crash.
367 PlatformThread::Sleep(50);
368 }
369
370 std::string times;
371 for (int i = 0; i < kNumCycles; ++i)
372 StringAppendF(&times, "%.2f,", timings[i].InMillisecondsF());
373
374 PrintResultList(graph, "", trace, times, "ms", important);
375 }
376
377 FilePath dir_app_;
378 FilePath chrome_dll_;
379 FilePath chrome_exe_;
380 FilePath chrome_frame_dll_;
381
382 protected:
383 // Individual startup tests should implement this function.
384 virtual void RunStartupTestImpl(TimeTicks* start_time,
385 TimeTicks* end_time) {}
386
387 // The host is torn down by this function. It should not be used after
388 // this function returns.
389 static void ReleaseHostComReferences(CAxWindow& host) {
390 CComPtr<IAxWinHostWindow> spWinHost;
391 host.QueryHost(&spWinHost);
392 ASSERT_TRUE(spWinHost != NULL);
393
394 // Hack to get the host to release all interfaces and thus ensure that
395 // the COM server can be unloaded.
396 CAxHostWindow* host_window = static_cast<CAxHostWindow*>(spWinHost.p);
397 host_window->ReleaseAll();
398 host.DestroyWindow();
399 }
400
401 std::string startup_url_;
402 };
403
404 class ChromeFrameStartupTestActiveX : public ChromeFrameStartupTest {
405 public:
406 virtual void SetUp() {
407 // Register the Chrome Frame DLL in the build directory.
408 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar);
409
410 ChromeFrameStartupTest::SetUp();
411 }
412
413 protected:
414 virtual void RunStartupTestImpl(TimeTicks* start_time,
415 TimeTicks* end_time) {
416 *start_time = TimeTicks::Now();
417 SimpleModule module;
418 AtlAxWinInit();
419 CComObjectStackEx<ChromeFrameActiveXContainer> wnd;
420 wnd.CreateChromeFrameWindow(startup_url_);
421 wnd.CreateControl(true);
422 module.RunMessageLoop();
423 *end_time = TimeTicks::Now();
424 }
425 };
426
427 // This class measures the load time of chrome and chrome frame binaries
428 class ChromeFrameBinariesLoadTest : public ChromeFrameStartupTestActiveX {
429 protected:
430 virtual void RunStartupTestImpl(TimeTicks* start_time,
431 TimeTicks* end_time) {
432 *start_time = TimeTicks::Now();
433
434 HMODULE chrome_exe = LoadLibrary(chrome_exe_.ToWStringHack().c_str());
435 ASSERT_TRUE(chrome_exe != NULL);
436
437 HMODULE chrome_dll = LoadLibrary(chrome_dll_.ToWStringHack().c_str());
438 ASSERT_TRUE(chrome_dll != NULL);
439
440 HMODULE chrome_tab_dll =
441 LoadLibrary(chrome_frame_dll_.ToWStringHack().c_str());
442 ASSERT_TRUE(chrome_tab_dll != NULL);
443
444 *end_time = TimeTicks::Now();
445
446 FreeLibrary(chrome_exe);
447 FreeLibrary(chrome_dll);
448 FreeLibrary(chrome_tab_dll);
449 }
450 };
451
452 // This class provides functionality to run the startup performance test for
453 // the ChromeFrame ActiveX against a reference build. At this point we only run
454 // this test in warm mode.
455 class ChromeFrameStartupTestActiveXReference
456 : public ChromeFrameStartupTestActiveX {
457 public:
458 // override the browser directory to use the reference build instead.
459 virtual void SetUp() {
460 // Register the reference build Chrome Frame DLL.
461 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar);
462 chrome_frame_registrar_->RegisterReferenceChromeFrameBuild();
463
464 ChromeFrameStartupTest::SetUp();
465 chrome_frame_dll_ = FilePath::FromWStringHack(
466 chrome_frame_registrar_->GetChromeFrameDllPath());
467 }
468
469 virtual void TearDown() {
470 // Reregister the Chrome Frame DLL in the build directory.
471 chrome_frame_registrar_.reset(NULL);
472 }
473 };
474
475 // This class provides base functionality to measure ChromeFrame memory
476 // usage.
477 // TODO(iyengar)
478 // Some of the functionality in this class like printing the results, etc
479 // is based on the chrome\test\memory_test.cc. We need to factor out
480 // the common code.
481 class ChromeFrameMemoryTest : public ChromeFramePerfTestBase {
482
483 // Contains information about the memory consumption of a process.
484 class ProcessMemoryInfo {
485 public:
486 // Default constructor
487 // Added to enable us to add ProcessMemoryInfo instances to a map.
488 ProcessMemoryInfo()
489 : process_id_(0),
490 peak_virtual_size_(0),
491 virtual_size_(0),
492 peak_working_set_size_(0),
493 working_set_size_(0),
494 chrome_browser_process_(false),
495 chrome_frame_memory_test_instance_(NULL) {}
496
497 ProcessMemoryInfo(base::ProcessId process_id, bool chrome_browser_process,
498 ChromeFrameMemoryTest* memory_test_instance)
499 : process_id_(process_id),
500 peak_virtual_size_(0),
501 virtual_size_(0),
502 peak_working_set_size_(0),
503 working_set_size_(0),
504 chrome_browser_process_(chrome_browser_process),
505 chrome_frame_memory_test_instance_(memory_test_instance) {}
506
507 bool GetMemoryConsumptionDetails() {
508 return GetMemoryInfo(process_id_,
509 &peak_virtual_size_,
510 &virtual_size_,
511 &peak_working_set_size_,
512 &working_set_size_);
513 }
514
515 void Print(const char* test_name) {
516 std::string trace_name(test_name);
517
518 ASSERT_TRUE(chrome_frame_memory_test_instance_ != NULL);
519
520 if (chrome_browser_process_) {
521 chrome_frame_memory_test_instance_->PrintResult(
522 "vm_final_browser", "", trace_name + "_vm_b",
523 virtual_size_ / 1024, "KB", false /* not important */);
524 chrome_frame_memory_test_instance_->PrintResult(
525 "ws_final_browser", "", trace_name + "_ws_b",
526 working_set_size_ / 1024, "KB", false /* not important */);
527 } else if (process_id_ == GetCurrentProcessId()) {
528 chrome_frame_memory_test_instance_->PrintResult(
529 "vm_current_process", "", trace_name + "_vm_c",
530 virtual_size_ / 1024, "KB", false /* not important */);
531 chrome_frame_memory_test_instance_->PrintResult(
532 "ws_current_process", "", trace_name + "_ws_c",
533 working_set_size_ / 1024, "KB", false /* not important */);
534 }
535
536 printf("\n");
537 }
538
539 int process_id_;
540 size_t peak_virtual_size_;
541 size_t virtual_size_;
542 size_t peak_working_set_size_;
543 size_t working_set_size_;
544 // Set to true if this is the chrome browser process.
545 bool chrome_browser_process_;
546
547 // A reference to the ChromeFrameMemoryTest instance. Used to print memory
548 // consumption information.
549 ChromeFrameMemoryTest* chrome_frame_memory_test_instance_;
550 };
551
552 // This map tracks memory usage for a process. It is keyed on the process
553 // id.
554 typedef std::map<DWORD, ProcessMemoryInfo> ProcessMemoryConsumptionMap;
555
556 public:
557 ChromeFrameMemoryTest()
558 : current_url_index_(0),
559 browser_pid_(0) {}
560
561 virtual void SetUp() {
562 // Register the Chrome Frame DLL in the build directory.
563 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar);
564 }
565
566 void RunTest(const char* test_name, char* urls[], int total_urls) {
567 ASSERT_TRUE(urls != NULL);
568 ASSERT_GT(total_urls, 0);
569
570 // Record the initial CommitCharge. This is a system-wide measurement,
571 // so if other applications are running, they can create variance in this
572 // test.
573 start_commit_charge_ = GetSystemCommitCharge();
574
575 for (int i = 0; i < total_urls; i++)
576 urls_.push_back(urls[i]);
577
578 std::string url;
579 GetNextUrl(&url);
580 ASSERT_TRUE(!url.empty());
581
582 StartTest(url, test_name);
583 }
584
585 void OnNavigationSuccess(VARIANT* param) {
586 ASSERT_TRUE(param != NULL);
587 ASSERT_EQ(VT_BSTR, param->vt);
588
589 DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal;
590 InitiateNextNavigation();
591 }
592
593 void OnNavigationFailure(VARIANT* param) {
594 ASSERT_TRUE(param != NULL);
595 ASSERT_EQ(VT_BSTR, param->vt);
596
597 DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal;
598 InitiateNextNavigation();
599 }
600
601 protected:
602 bool GetNextUrl(std::string* url) {
603 if (current_url_index_ >= urls_.size())
604 return false;
605
606 *url = urls_[current_url_index_++];
607 return true;
608 }
609
610 // Returns the path of the current chrome.exe being used by this test.
611 // This could return the regular chrome path or that of the reference
612 // build.
613 std::wstring GetChromeExePath() {
614 std::wstring chrome_exe_path =
615 chrome_frame_registrar_->GetChromeFrameDllPath();
616 EXPECT_FALSE(chrome_exe_path.empty());
617
618 file_util::UpOneDirectory(&chrome_exe_path);
619
620 std::wstring chrome_exe_test_path = chrome_exe_path;
621 file_util::AppendToPath(&chrome_exe_test_path,
622 chrome::kBrowserProcessExecutableName);
623
624 if (!file_util::PathExists(chrome_exe_test_path)) {
625 file_util::UpOneDirectory(&chrome_exe_path);
626
627 chrome_exe_test_path = chrome_exe_path;
628 file_util::AppendToPath(&chrome_exe_test_path,
629 chrome::kBrowserProcessExecutableName);
630 }
631
632 EXPECT_TRUE(file_util::PathExists(chrome_exe_test_path));
633
634 return chrome_exe_path;
635 }
636
637 void InitiateNextNavigation() {
638 if (browser_pid_ == 0) {
639 std::wstring profile_directory;
640 if (GetUserProfileBaseDirectory(&profile_directory)) {
641 file_util::AppendToPath(&profile_directory,
642 GetHostProcessName(false));
643 }
644
645 user_data_dir_ = FilePath::FromWStringHack(profile_directory);
646 browser_pid_ = ChromeBrowserProcessId(user_data_dir_);
647 }
648
649 EXPECT_TRUE(static_cast<int>(browser_pid_) > 0);
650
651 // Get the memory consumption information for the child processes
652 // of the chrome browser.
653 ChromeProcessList child_processes = GetBrowserChildren();
654 ChromeProcessList::iterator index;
655 for (index = child_processes.begin(); index != child_processes.end();
656 ++index) {
657 AccountProcessMemoryUsage(*index);
658 }
659
660 // TODO(iyengar): Bug 2953
661 // Need to verify if this is still true.
662 // The automation crashes periodically if we cycle too quickly.
663 // To make these tests more reliable, slowing them down a bit.
664 Sleep(200);
665
666 std::string url;
667 bool next_url = GetNextUrl(&url);
668 if (!url.empty()) {
669 NavigateImpl(url);
670 } else {
671 TestCompleted();
672 }
673 }
674
675 void PrintResults(const char* test_name) {
676 PrintMemoryUsageInfo(test_name);
677 memory_consumption_map_.clear();
678
679 // Added to give the OS some time to flush the used pages for the
680 // chrome processes which would have exited by now.
681 Sleep(200);
682
683 size_t end_commit_charge = GetSystemCommitCharge();
684 size_t commit_size = end_commit_charge - start_commit_charge_;
685
686 std::string trace_name(test_name);
687 trace_name.append("_cc");
688
689 PrintResult("commit_charge", "", trace_name,
690 commit_size / 1024, "KB", true /* important */);
691 printf("\n");
692 }
693
694 ChromeProcessList GetBrowserChildren() {
695 ChromeProcessList list = GetRunningChromeProcesses(user_data_dir_);
696 ChromeProcessList::iterator browser =
697 std::find(list.begin(), list.end(), browser_pid_);
698 if (browser != list.end()) {
699 list.erase(browser);
700 }
701 return list;
702 }
703
704 void AccountProcessMemoryUsage(DWORD process_id) {
705 ProcessMemoryInfo process_memory_info(process_id,
706 process_id == browser_pid_, this);
707
708 ASSERT_TRUE(process_memory_info.GetMemoryConsumptionDetails());
709
710 memory_consumption_map_[process_id] = process_memory_info;
711 }
712
713 void PrintMemoryUsageInfo(const char* test_name) {
714 printf("\n");
715
716 std::string trace_name(test_name);
717
718 ProcessMemoryConsumptionMap::iterator index;
719 size_t total_virtual_size = 0;
720 size_t total_working_set_size = 0;
721
722 for (index = memory_consumption_map_.begin();
723 index != memory_consumption_map_.end();
724 ++index) {
725 ProcessMemoryInfo& memory_info = (*index).second;
726 memory_info.Print(test_name);
727
728 total_virtual_size += memory_info.virtual_size_;
729 total_working_set_size += memory_info.working_set_size_;
730 }
731
732 printf("\n");
733
734 PrintResult("vm_final_total", "", trace_name + "_vm",
735 total_virtual_size / 1024, "KB",
736 false /* not important */);
737 PrintResult("ws_final_total", "", trace_name + "_ws",
738 total_working_set_size / 1024, "KB",
739 true /* important */);
740 }
741
742 // Should never get called.
743 virtual void StartTest(const std::string& url,
744 const std::string& test_name) = 0 {
745 ASSERT_FALSE(false);
746 }
747
748 // Should never get called.
749 virtual void NavigateImpl(const std::string& url) = 0 {
750 ASSERT_FALSE(false);
751 }
752
753 virtual void TestCompleted() = 0 {
754 ASSERT_FALSE(false);
755 }
756
757 // Holds the commit charge at the start of the memory test run.
758 size_t start_commit_charge_;
759
760 // The index of the URL being tested.
761 size_t current_url_index_;
762
763 // The chrome browser pid.
764 base::ProcessId browser_pid_;
765
766 // Contains the list of urls against which the tests are run.
767 std::vector<std::string> urls_;
768
769 ProcessMemoryConsumptionMap memory_consumption_map_;
770 };
771
772 // This class provides functionality to run the memory test against a reference
773 // chrome frame build.
774 class ChromeFrameMemoryTestReference : public ChromeFrameMemoryTest {
775 public:
776 virtual void SetUp() {
777 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar);
778 chrome_frame_registrar_->RegisterReferenceChromeFrameBuild();
779 }
780
781 virtual void TearDown() {
782 // Reregisters the chrome frame DLL in the build directory.
783 chrome_frame_registrar_.reset(NULL);
784 }
785 };
786
787 // This class overrides the hooks provided by the ChromeFrameActiveXContainer
788 // class and calls back into the ChromeFrameMemoryTest object instance,
789 // which measures ChromeFrame memory usage.
790 class ChromeFrameActiveXContainerMemory : public ChromeFrameActiveXContainer {
791 public:
792 ChromeFrameActiveXContainerMemory()
793 : delegate_(NULL) {}
794
795 ~ChromeFrameActiveXContainerMemory() {}
796
797 void Initialize(ChromeFrameMemoryTest* delegate) {
798 ASSERT_TRUE(delegate != NULL);
799 delegate_ = delegate;
800 }
801
802 protected:
803 virtual void OnLoadCallbackImpl(VARIANT* param) {
804 delegate_->OnNavigationSuccess(param);
805 }
806
807 virtual void OnLoadErrorCallbackImpl(VARIANT* param) {
808 delegate_->OnNavigationFailure(param);
809 }
810
811 ChromeFrameMemoryTest* delegate_;
812 };
813
814 // This class runs memory tests against the ChromeFrame ActiveX.
815 template<class MemoryTestBase>
816 class ChromeFrameActiveXMemoryTest : public MemoryTestBase {
817 public:
818 ChromeFrameActiveXMemoryTest()
819 : chrome_frame_container_(NULL),
820 test_completed_(false) {}
821
822 ~ChromeFrameActiveXMemoryTest() {
823 }
824
825 void StartTest(const std::string& url, const std::string& test_name) {
826 ASSERT_TRUE(chrome_frame_container_ == NULL);
827
828 test_name_ = test_name;
829
830 SimpleModule module;
831 AtlAxWinInit();
832
833 CComObject<ChromeFrameActiveXContainerMemory>::CreateInstance(
834 &chrome_frame_container_);
835 chrome_frame_container_->AddRef();
836
837 chrome_frame_container_->Initialize(this);
838
839 chrome_frame_container_->CreateChromeFrameWindow(url.c_str());
840 chrome_frame_container_->CreateControl(true);
841
842 module.RunMessageLoop();
843
844 chrome_frame_container_->Release();
845
846 PrintResults(test_name_.c_str());
847
848 CoFreeUnusedLibraries();
849 //ASSERT_TRUE(GetModuleHandle(L"npchrome_tab.dll") == NULL);
850 }
851
852 void NavigateImpl(const std::string& url) {
853 ASSERT_TRUE(chrome_frame_container_ != NULL);
854 ASSERT_TRUE(!url.empty());
855 chrome_frame_container_->Navigate(url.c_str());
856 }
857
858 void TestCompleted() {
859 // This can get called multiple times if the last url results in a
860 // redirect.
861 if (!test_completed_) {
862 ASSERT_NE(browser_pid_, 0);
863
864 // Measure memory usage for the browser process.
865 AccountProcessMemoryUsage(browser_pid_);
866 // Measure memory usage for the current process.
867 AccountProcessMemoryUsage(GetCurrentProcessId());
868
869 test_completed_ = true;
870 EXPECT_TRUE(PostMessage(static_cast<HWND>(*chrome_frame_container_),
871 WM_CLOSE, 0, 0));
872 }
873 }
874
875 protected:
876 CComObject<ChromeFrameActiveXContainerMemory>* chrome_frame_container_;
877 std::string test_name_;
878 bool test_completed_;
879 };
880
881 // This class runs tests to measure chrome frame creation only. This will help
882 // track overall page load performance with chrome frame instances.
883 class ChromeFrameCreationTest : public ChromeFrameStartupTest {
884 protected:
885 virtual void RunStartupTestImpl(TimeTicks* start_time,
886 TimeTicks* end_time) {
887 SimpleModule module;
888 AtlAxWinInit();
889 CComObjectStackEx<ChromeFrameActiveXContainer> wnd;
890 wnd.CreateChromeFrameWindow(startup_url_);
891 *start_time = TimeTicks::Now();
892 wnd.CreateControl(false);
893 *end_time = TimeTicks::Now();
894 }
895 };
896
897 // This class provides functionality to run the chrome frame
898 // performance test against a reference build.
899 class ChromeFrameCreationTestReference : public ChromeFrameCreationTest {
900 public:
901 // override the browser directory to use the reference build instead.
902 virtual void SetUp() {
903 chrome_frame_registrar_.reset(new ScopedChromeFrameRegistrar);
904 chrome_frame_registrar_->RegisterReferenceChromeFrameBuild();
905 ChromeFrameStartupTest::SetUp();
906 }
907
908 virtual void TearDown() {
909 chrome_frame_registrar_.reset(NULL);
910 }
911 };
912
913 // This class measures the creation time for Flash, which would be used
914 // as a baseline to measure chrome frame creation performance.
915 class FlashCreationTest : public ChromeFrameStartupTest {
916 protected:
917 virtual void RunStartupTestImpl(TimeTicks* start_time,
918 TimeTicks* end_time) {
919 SimpleModule module;
920 AtlAxWinInit();
921 CAxWindow host;
922 RECT rc = {0, 0, 800, 600};
923 host.Create(NULL, rc, NULL,
924 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
925 WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
926 EXPECT_TRUE(host.m_hWnd != NULL);
927
928 *start_time = TimeTicks::Now();
929 HRESULT hr = host.CreateControl(L"ShockwaveFlash.ShockwaveFlash");
930 EXPECT_HRESULT_SUCCEEDED(hr);
931 *end_time = TimeTicks::Now();
932
933 ReleaseHostComReferences(host);
934 }
935 };
936
937 // This class measures the creation time for Silverlight, which would be used
938 // as a baseline to measure chrome frame creation performance.
939 class SilverlightCreationTest : public ChromeFrameStartupTest {
940 protected:
941 virtual void RunStartupTestImpl(TimeTicks* start_time,
942 TimeTicks* end_time) {
943 SimpleModule module;
944 AtlAxWinInit();
945 CAxWindow host;
946 RECT rc = {0, 0, 800, 600};
947 host.Create(NULL, rc, NULL,
948 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
949 WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
950 EXPECT_TRUE(host.m_hWnd != NULL);
951
952 *start_time = TimeTicks::Now();
953 HRESULT hr = host.CreateControl(L"AgControl.AgControl");
954 EXPECT_HRESULT_SUCCEEDED(hr);
955 *end_time = TimeTicks::Now();
956
957 ReleaseHostComReferences(host);
958 }
959 };
960
961 TEST(ChromeFramePerf, DISABLED_HostActiveX) {
962 // TODO(stoyan): Create a low integrity level thread && perform the test there
963 SimpleModule module;
964 AtlAxWinInit();
965 CComObjectStackEx<ChromeFrameActiveXContainerPerf> wnd;
966 wnd.CreateChromeFrameWindow("http://www.google.com");
967 wnd.CreateControl(true);
968 module.RunMessageLoop();
969 }
970
971 TEST(ChromeFramePerf, DISABLED_HostActiveXInvalidURL) {
972 // TODO(stoyan): Create a low integrity level thread && perform the test there
973 SimpleModule module;
974 AtlAxWinInit();
975 CComObjectStackEx<ChromeFrameActiveXContainerPerf> wnd;
976 wnd.CreateChromeFrameWindow("http://non-existent-domain.org/");
977 wnd.CreateControl(true);
978 module.RunMessageLoop();
979 }
980
981 TEST_F(ChromeFrameStartupTestActiveX, PerfWarm) {
982 RunStartupTest("warm", "t", "about:blank", false /* cold */, 0, NULL,
983 true /* important */, false);
984 }
985
986 TEST_F(ChromeFrameBinariesLoadTest, PerfWarm) {
987 RunStartupTest("binary_load_warm", "t", "", false /* cold */, 0, NULL,
988 true /* important */, false);
989 }
990
991 TEST_F(ChromeFrameStartupTestActiveX, PerfCold) {
992 FilePath binaries_to_evict[] = {chrome_exe_, chrome_dll_, chrome_frame_dll_};
993 RunStartupTest("cold", "t", "about:blank", true /* cold */,
994 arraysize(binaries_to_evict), binaries_to_evict,
995 false /* not important */, false);
996 }
997
998 TEST_F(ChromeFrameBinariesLoadTest, PerfCold) {
999 FilePath binaries_to_evict[] = {chrome_exe_, chrome_dll_, chrome_frame_dll_};
1000 RunStartupTest("binary_load_cold", "t", "", true /* cold */,
1001 arraysize(binaries_to_evict), binaries_to_evict,
1002 false /* not important */, false);
1003 }
1004
1005 TEST_F(ChromeFrameStartupTestActiveXReference, PerfWarm) {
1006 RunStartupTest("warm", "t_ref", "about:blank", false /* cold */, 0, NULL,
1007 true /* important */, false);
1008 }
1009
1010 TEST_F(ChromeFrameStartupTestActiveX, PerfChromeFrameInitializationWarm) {
1011 RunStartupTest("ChromeFrame_init_warm", "t", "", false /* cold */, 0,
1012 NULL, true /* important */, false);
1013 }
1014
1015 TEST_F(ChromeFrameStartupTestActiveX, PerfChromeFrameInitializationCold) {
1016 FilePath binaries_to_evict[] = {chrome_frame_dll_};
1017 RunStartupTest("ChromeFrame_init_cold", "t", "", true /* cold */,
1018 arraysize(binaries_to_evict), binaries_to_evict,
1019 false /* not important */, false);
1020 }
1021
1022 TEST_F(ChromeFrameStartupTestActiveXReference,
1023 PerfChromeFrameInitializationWarm) {
1024 RunStartupTest("ChromeFrame_init_warm", "t_ref", "", false /* cold */, 0,
1025 NULL, true /* important */, false);
1026 }
1027
1028 typedef ChromeFrameActiveXMemoryTest<ChromeFrameMemoryTest>
1029 RegularChromeFrameActiveXMemoryTest;
1030
1031 TEST_F(RegularChromeFrameActiveXMemoryTest, MemoryTestAboutBlank) {
1032 char *urls[] = {"about:blank"};
1033 RunTest("memory_about_blank", urls, arraysize(urls));
1034 }
1035
1036 // TODO(iyengar)
1037 // Revisit why the chrome frame dll does not unload correctly when this test is
1038 // run.
1039 TEST_F(RegularChromeFrameActiveXMemoryTest, DISABLED_MemoryTestUrls) {
1040 // TODO(iyengar)
1041 // We should use static pages to measure memory usage.
1042 char *urls[] = {
1043 "http://www.youtube.com/watch?v=PN2HAroA12w",
1044 "http://www.youtube.com/watch?v=KmLJDrsaJmk&feature=channel"
1045 };
1046
1047 RunTest("memory", urls, arraysize(urls));
1048 }
1049
1050 typedef ChromeFrameActiveXMemoryTest<ChromeFrameMemoryTestReference>
1051 ReferenceBuildChromeFrameActiveXMemoryTest;
1052
1053 TEST_F(ReferenceBuildChromeFrameActiveXMemoryTest, MemoryTestAboutBlank) {
1054 char *urls[] = {"about:blank"};
1055 RunTest("memory_about_blank_reference", urls, arraysize(urls));
1056 }
1057
1058 // TODO(iyengar)
1059 // Revisit why the chrome frame dll does not unload correctly when this test is
1060 // run.
1061 TEST_F(ReferenceBuildChromeFrameActiveXMemoryTest, DISABLED_MemoryTestUrls) {
1062 // TODO(iyengar)
1063 // We should use static pages to measure memory usage.
1064 char *urls[] = {
1065 "http://www.youtube.com/watch?v=PN2HAroA12w",
1066 "http://www.youtube.com/watch?v=KmLJDrsaJmk&feature=channel"
1067 };
1068
1069 RunTest("memory_reference", urls, arraysize(urls));
1070 }
1071
1072 TEST_F(ChromeFrameCreationTest, PerfWarm) {
1073 RunStartupTest("creation_warm", "t", "", false /* cold */, 0,
1074 NULL, true /* important */, false);
1075 }
1076
1077 TEST_F(ChromeFrameCreationTestReference, PerfWarm) {
1078 RunStartupTest("creation_warm", "t_ref", "about:blank", false /* cold */, 0,
1079 NULL, true /* not important */, false);
1080 }
1081
1082 TEST_F(FlashCreationTest, PerfWarm) {
1083 RunStartupTest("creation_warm", "t_flash", "", false /* cold */, 0, NULL,
1084 true /* not important */, false);
1085 }
1086
1087 TEST_F(SilverlightCreationTest, DISABLED_PerfWarm) {
1088 RunStartupTest("creation_warm", "t_silverlight", "", false /* cold */, 0,
1089 NULL, false /* not important */, false);
1090 }
1091
1092 TEST_F(ChromeFrameCreationTest, PerfCold) {
1093 FilePath binaries_to_evict[] = {chrome_frame_dll_};
1094
1095 RunStartupTest("creation_cold", "t", "", true /* cold */,
1096 arraysize(binaries_to_evict), binaries_to_evict,
1097 true /* important */, false);
1098 }
1099
1100 // Attempt to evict the Flash control can fail on the buildbot as the dll
1101 // is marked read only. The test run is aborted if we fail to evict the file
1102 // from the cache. This could also fail if the Flash control is in use.
1103 // On Vista this could fail because of UAC
1104 TEST_F(FlashCreationTest, PerfCold) {
1105 RegKey flash_key(HKEY_CLASSES_ROOT, kFlashControlKey);
1106
1107 std::wstring plugin_path;
1108 ASSERT_TRUE(flash_key.ReadValue(L"", &plugin_path));
1109 ASSERT_FALSE(plugin_path.empty());
1110
1111 FilePath flash_path = FilePath::FromWStringHack(plugin_path);
1112 FilePath binaries_to_evict[] = {flash_path};
1113
1114 RunStartupTest("creation_cold", "t_flash", "", true /* cold */,
1115 arraysize(binaries_to_evict), binaries_to_evict,
1116 false/* important */, true);
1117 }
1118
1119 // This test would fail on Vista due to UAC or if the Silverlight control is
1120 // in use. The test run is aborted if we fail to evict the file from the cache.
1121 // Disabling this test as the Silverlight dll does not seem to get unloaded
1122 // correctly causing the attempt to evict the dll from the system cache to
1123 // fail.
1124 TEST_F(SilverlightCreationTest, DISABLED_PerfCold) {
1125 RegKey silverlight_key(HKEY_CLASSES_ROOT, kSilverlightControlKey);
1126
1127 std::wstring plugin_path;
1128 ASSERT_TRUE(silverlight_key.ReadValue(L"", &plugin_path));
1129 ASSERT_FALSE(plugin_path.empty());
1130
1131 FilePath silverlight_path = FilePath::FromWStringHack(plugin_path);
1132 FilePath binaries_to_evict[] = {silverlight_path};
1133
1134 RunStartupTest("creation_cold", "t_silverlight", "", true /* cold */,
1135 arraysize(binaries_to_evict), binaries_to_evict,
1136 false /* important */, true);
1137 }
OLDNEW
« no previous file with comments | « chrome_frame/test/perf/chrome_frame_perftest.h ('k') | chrome_frame/test/perf/chrometab_perftests.vcproj » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698