diff options
author | ccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-11 16:02:46 +0000 |
---|---|---|
committer | ccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-11 16:02:46 +0000 |
commit | 4d66a016257c355b7c084f6e554031660bf131e3 (patch) | |
tree | 98d18729e139c4ceecc89d3f542eb1284ea9b126 /content/browser/gpu/gpu_memory_test.cc | |
parent | 3f8a01e84bdcac7f8cb1d397681cf3563aa6ea77 (diff) | |
download | chromium_src-4d66a016257c355b7c084f6e554031660bf131e3.zip chromium_src-4d66a016257c355b7c084f6e554031660bf131e3.tar.gz chromium_src-4d66a016257c355b7c084f6e554031660bf131e3.tar.bz2 |
Enable a simple GPU memory manager browser test.
Add a mechanism for waiting for RequestAnimationFrames from each
visible tab. Outline the structure for flushing out pending GPU
work.
Add gpu as a explicit dependency of content_browsertests so that we
can specify the kForceGpuMemAvailableMb in component builds.
BUG=135525
Review URL: https://chromiumcodereview.appspot.com/11826013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@176358 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/gpu/gpu_memory_test.cc')
-rw-r--r-- | content/browser/gpu/gpu_memory_test.cc | 125 |
1 files changed, 100 insertions, 25 deletions
diff --git a/content/browser/gpu/gpu_memory_test.cc b/content/browser/gpu/gpu_memory_test.cc index 75ea141..9312651 100644 --- a/content/browser/gpu/gpu_memory_test.cc +++ b/content/browser/gpu/gpu_memory_test.cc @@ -20,6 +20,13 @@ namespace { +// Run the tests with a memory limit of 256MB, and give +// and extra 4MB of wiggle-room for over-allocation. +const char* kMemoryLimitMBSwitch = "256"; +const size_t kMemoryLimitMB = 256; +const size_t kSingleTabLimitMB = 128; +const size_t kWiggleRoomMB = 4; + // Observer to report GPU memory usage when requested. class GpuMemoryBytesAllocatedObserver : public content::GpuDataManagerObserver { @@ -74,9 +81,8 @@ class GpuMemoryTest : public content::ContentBrowserTest { virtual void SetUpCommandLine(CommandLine* command_line) { command_line->AppendSwitch(switches::kEnableLogging); command_line->AppendSwitch(switches::kForceCompositingMode); - // TODO: Use switches::kForceGpuMemAvailableMb to fix the memory limit - // (this is failing some bots (probably because of differing meanings of - // GPU_EXPORT) + command_line->AppendSwitchASCII(switches::kForceGpuMemAvailableMb, + kMemoryLimitMBSwitch); // Only run this on GPU bots for now. These tests should work with // any GPU process, but may be slow. if (command_line->HasSwitch(switches::kUseGpuInTests)) { @@ -95,7 +101,7 @@ class GpuMemoryTest : public content::ContentBrowserTest { }; // Load a page and consume a specified amount of GPU memory. - void LoadPage(content::Shell* shell_to_load, + void LoadPage(content::Shell* tab_to_load, PageType page_type, size_t mb_to_use) { FilePath url; @@ -108,17 +114,19 @@ class GpuMemoryTest : public content::ContentBrowserTest { break; } - content::NavigateToURL(shell_to_load, net::FilePathToFileURL(url)); + content::NavigateToURL(tab_to_load, net::FilePathToFileURL(url)); std::ostringstream js_call; js_call << "useGpuMemory("; js_call << mb_to_use; js_call << ");"; - content::DOMMessageQueue message_queue; std::string message; - ASSERT_TRUE(content::ExecuteScript( - shell_to_load->web_contents(), js_call.str())); - ASSERT_TRUE(message_queue.WaitForMessage(&message)); - EXPECT_EQ("\"DONE_USE_GPU_MEMORY\"", message); + ASSERT_TRUE( + content::ExecuteScriptInFrameAndExtractString( + tab_to_load->web_contents(), + "", + js_call.str(), + &message)); + EXPECT_EQ("DONE_USE_GPU_MEMORY", message); } // Create a new tab. @@ -126,22 +134,48 @@ class GpuMemoryTest : public content::ContentBrowserTest { // The ContentBrowserTest will create one shell by default, use that one // first so that we don't confuse the memory manager into thinking there // are more windows than there are. - content::Shell* new_shell = + content::Shell* new_tab = has_used_first_shell_ ? CreateBrowser() : shell(); has_used_first_shell_ = true; - visible_shells_.insert(new_shell); - return new_shell; + tabs_.insert(new_tab); + visible_tabs_.insert(new_tab); + return new_tab; } - void SetTabBackgrounded(content::Shell* shell_to_background) { + void SetTabBackgrounded(content::Shell* tab_to_background) { ASSERT_TRUE( - visible_shells_.find(shell_to_background) != visible_shells_.end()); - visible_shells_.erase(shell_to_background); - shell_to_background->web_contents()->WasHidden(); + visible_tabs_.find(tab_to_background) != visible_tabs_.end()); + visible_tabs_.erase(tab_to_background); + tab_to_background->web_contents()->WasHidden(); } - size_t GetMemoryUsageMbytes() { - // TODO: This should wait until all effects of memory management complete. + bool MemoryUsageInRange(size_t low, size_t high) { + FinishGpuMemoryChanges(); + size_t memory_usage_bytes = GetMemoryUsageMbytes(); + + // If it's not immediately the case that low <= usage <= high, then + // allow + // Because we haven't implemented the full delay in FinishGpuMemoryChanges, + // keep re-reading the GPU memory usage for 2 seconds before declaring + // failure. + base::Time start_time = base::Time::Now(); + while (low > memory_usage_bytes || memory_usage_bytes > high) { + memory_usage_bytes = GetMemoryUsageMbytes(); + base::TimeDelta delta = base::Time::Now() - start_time; + if (delta.InMilliseconds() >= 2000) + break; + } + + return (low <= memory_usage_bytes && memory_usage_bytes <= high); + } + + bool AllowTestsToRun() const { + return allow_tests_to_run_; + } + + private: + void FinishGpuMemoryChanges() { + // This should wait until all effects of memory management complete. // We will need to wait until all // 1. pending commits from the main thread to the impl thread in the // compositor complete (for visible compositors). @@ -152,20 +186,61 @@ class GpuMemoryTest : public content::ContentBrowserTest { // manager are made. // Each step in this sequence can cause trigger the next (as a 1-2-3-4-1 // cycle), so we will need to pump this cycle until it stabilizes. + + // Pump the cycle 8 times (in principle it could take an infinite number + // of iterations to settle). + for (size_t pump_it = 0; pump_it < 8; ++pump_it) { + // Wait for a RequestAnimationFrame to complete from all visible tabs + // for stage 1 of the cycle. + for (std::set<content::Shell*>::iterator it = visible_tabs_.begin(); + it != visible_tabs_.end(); + ++it) { + std::string js_call( + "window.webkitRequestAnimationFrame(function() {" + " domAutomationController.setAutomationId(1);" + " domAutomationController.send(\"DONE_RAF\");" + "})"); + std::string message; + ASSERT_TRUE( + content::ExecuteScriptInFrameAndExtractString( + (*it)->web_contents(), + "", + js_call, + &message)); + EXPECT_EQ("DONE_RAF", message); + } + // TODO(ccameron): send an IPC from Browser -> Renderer (delay it until + // painting finishes) -> GPU process (delay it until any pending manages + // happen) -> All Renderers -> Browser to flush parts 2, 3, and 4. + } + } + + size_t GetMemoryUsageMbytes() { GpuMemoryBytesAllocatedObserver observer; observer.GetBytesAllocated(); return observer.GetBytesAllocated() / 1048576; } - bool AllowTestsToRun() const { - return allow_tests_to_run_; - } - - private: bool allow_tests_to_run_; - std::set<content::Shell*> visible_shells_; + std::set<content::Shell*> tabs_; + std::set<content::Shell*> visible_tabs_; bool has_used_first_shell_; FilePath gpu_test_dir_; }; +// When trying to load something that doesn't fit into our total GPU memory +// limit, we shouldn't exceed that limit. +IN_PROC_BROWSER_TEST_F(GpuMemoryTest, SingleWindowDoesNotExceedLimit) { + if (!AllowTestsToRun()) + return; + + content::Shell* tab = CreateNewTab(); + LoadPage(tab, PAGE_CSS3D, kMemoryLimitMB); + // Make sure that the CSS3D page maxes out a single tab's budget (otherwise + // the test doesn't test anything) but still stays under the limit. + EXPECT_TRUE(MemoryUsageInRange( + kSingleTabLimitMB - kWiggleRoomMB, + kMemoryLimitMB + kWiggleRoomMB)); +} + } // namespace |