Index: chrome/test/functional/perf.py |
diff --git a/chrome/test/functional/perf.py b/chrome/test/functional/perf.py |
index 174f73131618b659a1e2bb39407460cda8360210..5a47ae73d00b82386acde7924e38bc1a9183b85e 100755 |
--- a/chrome/test/functional/perf.py |
+++ b/chrome/test/functional/perf.py |
@@ -90,7 +90,7 @@ class BasePerfTest(pyauto.PyUITest): |
# TODO(dennisjeffrey): Implement wait for idle CPU on Windows/Mac. |
if self.IsLinux(): # IsLinux() also implies IsChromeOS(). |
os.system('sync') |
- self._WaitForIdleCPU(60.0, 0.03) |
+ self._WaitForIdleCPU(60.0, 0.05) |
def _WaitForIdleCPU(self, timeout, utilization): |
"""Waits for the CPU to become idle (< utilization). |
@@ -1765,6 +1765,133 @@ class PageCyclerTest(BasePerfTest): |
self._RunPageCyclerTest('moz2', self._num_iterations, 'Moz2File') |
+class MemoryTest(BasePerfTest): |
+ """Tests to measure memory consumption under different usage scenarios.""" |
+ |
+ def setUp(self): |
+ pyauto.PyUITest.setUp(self) |
+ |
ilja
2012/04/25 23:37:37
I assume you are logging out to use a fresh copy o
dennis_jeffrey
2012/04/26 01:46:25
Done.
|
+ if self.GetLoginInfo()['is_logged_in']: |
+ self.Logout() |
+ self.assertFalse(self.GetLoginInfo()['is_logged_in'], |
+ msg='Failed to log out.') |
+ |
+ # Log in. |
+ credentials = self.GetPrivateInfo()['test_google_account'] |
+ self.Login(credentials['username'], credentials['password']) |
+ self.assertTrue(self.GetLoginInfo()['is_logged_in'], |
+ msg='Failed to log in.') |
+ |
+ def _GetMemoryStats(self, duration=10): |
ilja
2012/04/25 23:37:37
I spoke with James and he thinks duration should b
dennis_jeffrey
2012/04/26 01:46:25
I removed the default value to force the caller to
|
+ """Identifies and returns different kinds of current memory usage stats. |
+ |
+ This function samples values each second for |duration| seconds, then |
+ outputs the min, max, and ending values for each measurement type. |
+ |
+ Args: |
+ duration: The number of seconds to sample data before outputting the |
+ minimum, maximum, and ending values for each measurement type. |
+ |
+ Returns: |
+ A dictionary containing memory usage information. Each measurement type |
+ is associated with the min, max, and ending values from among all |
+ sampled values. Values are specified in KB. |
+ { |
+ 'gtt': { # GPU memory usage (graphics translation table) |
+ 'min': ..., |
+ 'max': ..., |
+ 'end': ..., |
+ }, |
+ 'mem_available': { ... }, # CPU available memory |
+ 'mem_shared': { ... }, # CPU shared memory |
+ } |
+ """ |
+ logging.debug('Sampling memory information for %d seconds...' % duration) |
+ stats = { |
+ 'gtt': [], |
+ 'mem_available': [], |
+ 'mem_shared': [], |
+ } |
+ |
+ for _ in xrange(duration): |
+ p = subprocess.Popen('grep bytes /sys/kernel/debug/dri/0/i915_gem_gtt', |
+ stdout=subprocess.PIPE, |
+ shell=True) |
+ stdout = p.communicate()[0] |
+ |
+ # GPU memory. |
+ gtt_used = re.search( |
+ 'Total [\d]+ objects, ([\d]+) bytes', stdout).group(1) |
+ stats['gtt'].append(int(gtt_used) / 1024.0) |
+ |
+ # CPU memory. |
+ stdout = '' |
+ with open('/proc/meminfo') as f: |
+ stdout = f.read() |
+ mem_free = re.search('MemFree:\s*([\d]+) kB', stdout).group(1) |
+ mem_dirty = re.search('Dirty:\s*([\d]+) kB', stdout).group(1) |
+ mem_active_file = re.search( |
+ 'Active\(file\):\s*([\d]+) kB', stdout).group(1) |
+ mem_inactive_file = re.search( |
+ 'Inactive\(file\):\s*([\d]+) kB', stdout).group(1) |
+ stats['mem_available'].append( |
+ (int(mem_active_file) + int(mem_inactive_file)) - int(mem_dirty) + |
+ int(mem_free)) |
+ |
+ mem_shared = re.search('Shmem:\s*([\d]+) kB', stdout).group(1) |
+ stats['mem_shared'].append(int(mem_shared)) |
+ |
+ time.sleep(1) |
+ |
+ # Compute min, max, and ending values to return. |
+ result = {} |
+ for measurement_type in stats: |
+ values = stats[measurement_type] |
+ result[measurement_type] = { |
+ 'min': min(values), |
+ 'max': max(values), |
+ 'end': values[-1], |
+ } |
+ |
+ return result |
+ |
+ def _RecordMemoryStats(self, description, when): |
+ mem = self._GetMemoryStats() |
ilja
2012/04/25 23:37:37
Lets not use the default duration here. If we are
dennis_jeffrey
2012/04/26 01:46:25
Now using 15 seconds as the duration for the empty
|
+ measurement_types = [ |
+ ('gtt', 'GTT'), |
+ ('mem_available', 'MemAvail'), |
+ ('mem_shared', 'MemShared'), |
+ ] |
+ for type_key, type_string in measurement_types: |
+ self._OutputPerfGraphValue( |
+ '%s-%sMin-%s' % (description, type_string, when), |
ilja
2012/04/25 23:37:37
'%s-Min%s-%s' etc. is easier to read and does not
dennis_jeffrey
2012/04/26 01:46:25
Done.
|
+ mem[type_key]['min'], 'KB', '%s-%s' % (description, type_string)) |
+ self._OutputPerfGraphValue( |
+ '%s-%sMax-%s' % (description, type_string, when), |
ilja
2012/04/25 23:37:37
dito
dennis_jeffrey
2012/04/26 01:46:25
Done.
|
+ mem[type_key]['max'], 'KB', '%s-%s' % (description, type_string)) |
+ self._OutputPerfGraphValue( |
+ '%s-%sEnd-%s' % (description, type_string, when), |
ilja
2012/04/25 23:37:37
dito
dennis_jeffrey
2012/04/26 01:46:25
Done.
|
+ mem[type_key]['end'], 'KB', '%s-%s' % (description, type_string)) |
+ |
+ def _RunTest(self, tabs, description): |
ilja
2012/04/25 23:37:37
_RunTest needs duration as parameter when we run w
dennis_jeffrey
2012/04/26 01:46:25
Done.
|
+ self._RecordMemoryStats(description, 'Start') |
ilja
2012/04/25 23:37:37
Can we call this Close0 to be consistent with the
dennis_jeffrey
2012/04/26 01:46:25
I changed it to "0Tabs0" to follow the same format
|
+ |
+ for iteration_num in xrange(2): |
+ for site in tabs: |
+ self.AppendTab(pyauto.GURL(site)) |
+ |
+ self._RecordMemoryStats(description, 'Open%d' % (iteration_num + 1)) |
ilja
2012/04/25 23:37:37
'%dTabs%d' % (len(tabs), iteration_num + 1)
dennis_jeffrey
2012/04/26 01:46:25
Done.
|
+ |
+ for _ in xrange(len(tabs)): |
+ self.GetBrowserWindow(0).GetTab(1).Close(True) |
+ |
+ self._RecordMemoryStats(description, 'Close%d' % (iteration_num + 1)) |
ilja
2012/04/25 23:37:37
'0Tabs%d'
dennis_jeffrey
2012/04/26 01:46:25
Done.
|
+ |
+ def testOpenCloseTabsControl(self): |
+ tabs = ['about:blank'] * 10 |
+ self._RunTest(tabs, 'MemCtrl') |
+ |
+ |
class PerfTestServerRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): |
"""Request handler for the local performance test server.""" |