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 import memory_expectations
7 from telemetry import benchmark
8 from telemetry.page import page_test
9 from telemetry.timeline import counter
10 from telemetry.timeline import model
13 SINGLE_TAB_LIMIT_MB = 192
16 test_harness_script = r"""
17 var domAutomationController = {};
18 domAutomationController._finished = false;
20 domAutomationController.send = function(msg) {
21 // This should wait until all effects of memory management complete.
22 // We will need to wait until all
23 // 1. pending commits from the main thread to the impl thread in the
24 // compositor complete (for visible compositors).
25 // 2. allocations that the renderer's impl thread will make due to the
26 // compositor and WebGL are completed.
27 // 3. pending GpuMemoryManager::Manage() calls to manage are made.
28 // 4. renderers' OnMemoryAllocationChanged callbacks in response to
30 // Each step in this sequence can cause trigger the next (as a 1-2-3-4-1
31 // cycle), so we will need to pump this cycle until it stabilizes.
33 // Pump the cycle 8 times (in principle it could take an infinite number
34 // of iterations to settle).
38 // Impl-side painting has changed the behavior of this test.
39 // Currently the background of the page shows up checkerboarded
40 // initially, causing the test to fail because the memory
41 // allocation is too low (no root layer). Temporarily increase the
42 // rAF count to 32 in order to make the test work reliably again.
44 // TODO(kbr): revert this change and put it back to 8 iterations.
45 var totalRafCount = 32;
48 if (rafCount == totalRafCount) {
49 domAutomationController._finished = true;
53 window.requestAnimationFrame(pumpRAF);
58 window.domAutomationController = domAutomationController;
60 window.addEventListener("load", function() {
65 class _MemoryValidator(page_test.PageTest):
66 def ValidateAndMeasurePage(self, page, tab, results):
67 timeline_data = tab.browser.StopTracing()
68 timeline_model = model.TimelineModel(timeline_data)
69 for process in timeline_model.GetAllProcesses():
70 if 'gpu.GpuMemoryUsage' in process.counters:
71 counter = process.GetCounter('gpu', 'GpuMemoryUsage')
72 mb_used = counter.samples[-1] / 1048576
74 if mb_used + WIGGLE_ROOM_MB < SINGLE_TAB_LIMIT_MB:
75 raise page_test.Failure(self._FormatException('low', mb_used))
77 if mb_used - WIGGLE_ROOM_MB > MEMORY_LIMIT_MB:
78 raise page_test.Failure(self._FormatException('high', mb_used))
80 def CustomizeBrowserOptions(self, options):
81 options.AppendExtraBrowserArgs('--enable-logging')
82 options.AppendExtraBrowserArgs(
83 '--force-gpu-mem-available-mb=%s' % MEMORY_LIMIT_MB)
85 def WillNavigateToPage(self, page, tab):
86 # FIXME: Remove webkit.console when blink.console lands in chromium and the
87 # ref builds are updated. crbug.com/386847
88 custom_categories = ['webkit.console', 'blink.console', 'gpu']
89 tab.browser.StartTracing(','.join(custom_categories), 60)
91 def _FormatException(self, low_or_high, mb_used):
92 return 'Memory allocation too %s (was %d MB, should be %d MB +/- %d MB)' % (
93 low_or_high, mb_used, SINGLE_TAB_LIMIT_MB, WIGGLE_ROOM_MB)
95 class Memory(benchmark.Benchmark):
96 """Tests GPU memory limits"""
97 test = _MemoryValidator
98 page_set = page_sets.MemoryTestsPageSet
100 def CreateExpectations(self, page_set):
101 return memory_expectations.MemoryExpectations()
103 def CreatePageSet(self, options):
104 page_set = super(Memory, self).CreatePageSet(options)
105 for page in page_set.pages:
106 page.script_to_evaluate_on_commit = test_harness_script