Initial version of a chrome memory test.  This is not yet done; as it still
causes intermittent chrome crashes.  But, checking in an intermediate step so
that others can play with it too.

Basic concept is to have a pre-loaded replay cache with interesting data.  This
test then drives chrome through automation, simulating a sequence of pages in
each tab
in a way that a user might also do so; this allows us to 
get per-tab caching of data similar to what the user would see.

Includes a logged in gmail session, a few pages that exercise some javascript,
several languages, and pages
from many mainstream sites.

Lots more can be done with this test going forward; for now the goal is to just
measure and track memory.



git-svn-id: svn://svn.chromium.org/chrome/trunk/src@361 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/chrome.sln b/chrome/chrome.sln
index 1bc6371..4cf02b48 100644
--- a/chrome/chrome.sln
+++ b/chrome/chrome.sln
@@ -1183,6 +1183,20 @@
 		{D9DDAF60-663F-49CC-90DC-3D08CC3D1B28} = {D9DDAF60-663F-49CC-90DC-3D08CC3D1B28}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memory_test", "test\memory_test\memory_test.vcproj", "{A5F831FD-9B9C-4FEF-9FBA-554817B734CE}"
+	ProjectSection(ProjectDependencies) = postProject
+		{1556EF78-C7E6-43C8-951F-F6B43AC0DD12} = {1556EF78-C7E6-43C8-951F-F6B43AC0DD12}
+		{1832A374-8A74-4F9E-B536-69A699B3E165} = {1832A374-8A74-4F9E-B536-69A699B3E165}
+		{5BF908A7-68FB-4A4B-99E3-8C749F1FE4EA} = {5BF908A7-68FB-4A4B-99E3-8C749F1FE4EA}
+		{8423AF0D-4B88-4EBF-94E1-E4D00D00E21C} = {8423AF0D-4B88-4EBF-94E1-E4D00D00E21C}
+		{899F1280-3441-4D1F-BA04-CCD6208D9146} = {899F1280-3441-4D1F-BA04-CCD6208D9146}
+		{A508ADD3-CECE-4E0F-8448-2F5E454DF551} = {A508ADD3-CECE-4E0F-8448-2F5E454DF551}
+		{BFE8E2A7-3B3B-43B0-A994-3058B852DB8B} = {BFE8E2A7-3B3B-43B0-A994-3058B852DB8B}
+		{C564F145-9172-42C3-BFCB-6014CA97DBCD} = {C564F145-9172-42C3-BFCB-6014CA97DBCD}
+		{CD9CA56E-4E94-444C-87D4-58CA1E6F300D} = {CD9CA56E-4E94-444C-87D4-58CA1E6F300D}
+		{EF5E94AB-B646-4E5B-A058-52EF07B8351C} = {EF5E94AB-B646-4E5B-A058-52EF07B8351C}
+	EndProjectSection
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -2066,6 +2080,16 @@
 		{A5C5D801-4026-49F2-BBF1-250941855306}.Release|Mixed Platforms.Build.0 = Release|Win32
 		{A5C5D801-4026-49F2-BBF1-250941855306}.Release|Win32.ActiveCfg = Release|Win32
 		{A5C5D801-4026-49F2-BBF1-250941855306}.Release|Win32.Build.0 = Release|Win32
+		{A5F831FD-9B9C-4FEF-9FBA-554817B734CE}.Debug|Any CPU.ActiveCfg = Debug|Win32
+		{A5F831FD-9B9C-4FEF-9FBA-554817B734CE}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+		{A5F831FD-9B9C-4FEF-9FBA-554817B734CE}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+		{A5F831FD-9B9C-4FEF-9FBA-554817B734CE}.Debug|Win32.ActiveCfg = Debug|Win32
+		{A5F831FD-9B9C-4FEF-9FBA-554817B734CE}.Debug|Win32.Build.0 = Debug|Win32
+		{A5F831FD-9B9C-4FEF-9FBA-554817B734CE}.Release|Any CPU.ActiveCfg = Release|Win32
+		{A5F831FD-9B9C-4FEF-9FBA-554817B734CE}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+		{A5F831FD-9B9C-4FEF-9FBA-554817B734CE}.Release|Mixed Platforms.Build.0 = Release|Win32
+		{A5F831FD-9B9C-4FEF-9FBA-554817B734CE}.Release|Win32.ActiveCfg = Release|Win32
+		{A5F831FD-9B9C-4FEF-9FBA-554817B734CE}.Release|Win32.Build.0 = Release|Win32
 		{AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug|Any CPU.ActiveCfg = Debug|Win32
 		{AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
 		{AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug|Mixed Platforms.Build.0 = Debug|Win32
@@ -2672,6 +2696,7 @@
 		{A493331B-3180-49FE-8D0E-D121645E63AD} = {2325D8C4-8EF5-42AC-8900-492225750DE4}
 		{A508ADD3-CECE-4E0F-8448-2F5E454DF551} = {EF78C1F9-AA17-4CA5-B6CB-39B37A73A3DA}
 		{A5C5D801-4026-49F2-BBF1-250941855306} = {2325D8C4-8EF5-42AC-8900-492225750DE4}
+		{A5F831FD-9B9C-4FEF-9FBA-554817B734CE} = {1174D37F-6ABB-45DA-81B3-C631281273B7}
 		{AA8A5A85-592B-4357-BC60-E0E91E026AF6} = {1088577A-0C49-4DE0-85CD-B68AD0BE55AA}
 		{AAC78796-B9A2-4CD9-BF89-09B03E92BF73} = {1174D37F-6ABB-45DA-81B3-C631281273B7}
 		{AFF332BF-AF3D-4D35-86FC-42A727F01D36} = {2325D8C4-8EF5-42AC-8900-492225750DE4}
diff --git a/chrome/common/chrome_process_filter.cc b/chrome/common/chrome_process_filter.cc
index 28bee47..2a11b48 100644
--- a/chrome/common/chrome_process_filter.cc
+++ b/chrome/common/chrome_process_filter.cc
@@ -35,17 +35,20 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 
-BrowserProcessFilter::BrowserProcessFilter() : browser_process_id_(0) {
+BrowserProcessFilter::BrowserProcessFilter(const std::wstring user_data_dir)
+    : browser_process_id_(0),
+      user_data_dir_(user_data_dir) {
   // Find the message window (if any) for the current user data directory,
   // and get its process ID.  We'll only count browser processes that either
   // have the same process ID or have that process ID as their parent.
 
-  std::wstring user_data_dir;
-  PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
+  if (user_data_dir_.length() == 0)
+    PathService::Get(chrome::DIR_USER_DATA, &user_data_dir_);
+
 
   HWND message_window = FindWindowEx(HWND_MESSAGE, NULL,
                                      chrome::kMessageWindowClass,
-                                     user_data_dir.c_str());
+                                     user_data_dir_.c_str());
   if (message_window)
     GetWindowThreadProcessId(message_window, &browser_process_id_);
 }
diff --git a/chrome/common/chrome_process_filter.h b/chrome/common/chrome_process_filter.h
index 5f1e2cdc..3039bc6 100644
--- a/chrome/common/chrome_process_filter.h
+++ b/chrome/common/chrome_process_filter.h
@@ -32,17 +32,21 @@
 
 #include "base/process_util.h"
 
-// Filter all chrome browser processes that run with the current user data
-// directory (chrome::DIR_USER_DATA).
+// Filter all chrome browser processes that run with the same user data
+// directory.
 class BrowserProcessFilter : public process_util::ProcessFilter {
  public:
-  BrowserProcessFilter();
+  // Create the filter for the given user_data_dir.
+  // If user_data_dir is an empty string, will use the PathService
+  // user_data_dir (e.g. chrome::DIR_USER_DATA).
+  explicit BrowserProcessFilter(const std::wstring user_data_dir);
 
   uint32 browser_process_id() const { return browser_process_id_; }
 
   virtual bool Includes(uint32 pid, uint32 parent_pid) const;
 
  private:
+  std::wstring user_data_dir_;
   DWORD browser_process_id_;
 
   DISALLOW_EVIL_CONSTRUCTORS(BrowserProcessFilter);
diff --git a/chrome/test/memory_test/memory_test.cc b/chrome/test/memory_test/memory_test.cc
new file mode 100644
index 0000000..9e233de
--- /dev/null
+++ b/chrome/test/memory_test/memory_test.cc
@@ -0,0 +1,383 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/process_util.h"
+#include "base/string_util.h"
+#include "chrome/browser/url_fixer_upper.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_process_filter.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/automation/window_proxy.h"
+#include "chrome/test/ui/ui_test.h"
+#include "chrome/test/perf/mem_usage.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_util.h"
+
+namespace {
+
+class MemoryTest : public UITest {
+ public:
+  MemoryTest() {
+    show_window_ = true;
+
+    // For now, turn off plugins because they crash like crazy.
+    // TODO(mbelshe): Fix Chrome to not crash with plugins.
+    CommandLine::AppendSwitch(&launch_arguments_, switches::kDisablePlugins);
+
+    // Use the playback cache, but don't use playback events.
+    CommandLine::AppendSwitch(&launch_arguments_, switches::kPlaybackMode);
+    CommandLine::AppendSwitch(&launch_arguments_, switches::kNoEvents);
+
+    // Compute the user-data-dir which contains our test cache.
+    PathService::Get(base::DIR_EXE, &user_data_dir_);
+    file_util::UpOneDirectory(&user_data_dir_);
+    file_util::UpOneDirectory(&user_data_dir_);
+    file_util::AppendToPath(&user_data_dir_, L"data");
+    file_util::AppendToPath(&user_data_dir_, L"memory_test");
+    file_util::AppendToPath(&user_data_dir_, L"general_mix");
+    CommandLine::AppendSwitchWithValue(&launch_arguments_,
+                                       switches::kUserDataDir,
+                                       user_data_dir_);
+  }
+
+  // TODO(mbelshe): Separate this data to an external file.
+  // This memory test loads a set of URLs across a set of tabs, maintaining the
+  // number of concurrent open tabs at num_target_tabs.
+  // <NEWTAB> is a special URL which informs the loop when we should create a
+  // new tab.
+  // <PAUSE> is a special URL that informs the loop to pause before proceeding
+  // to the next URL.
+  void RunTest(const wchar_t* test_name, int num_target_tabs) {
+    std::string urls[] = {
+      "http://www.yahoo.com/",
+      "http://hotjobs.yahoo.com/career-articles-the_biggest_resume_mistake_you_can_make-436",
+      "http://news.yahoo.com/s/ap/20080804/ap_on_re_mi_ea/odd_israel_home_alone",
+      "http://news.yahoo.com/s/nm/20080729/od_nm/subway_dc",
+      "http://search.yahoo.com/search?p=new+york+subway&ygmasrchbtn=web+search&fr=ush-news",
+      "<NEWTAB>",
+      "http://www.cnn.com/",
+      "http://www.cnn.com/2008/SHOWBIZ/TV/08/03/applegate.cancer.ap/index.html",
+      "http://www.cnn.com/2008/HEALTH/conditions/07/29/black.aids.report/index.html",
+      "http://www.cnn.com/POLITICS/",
+      "http://search.cnn.com/search.jsp?query=obama&type=web&sortBy=date&intl=false",
+      "<NEWTAB>",
+      "http://mail.google.com/",
+      "http://mail.google.com/mail/?shva=1",
+      "http://mail.google.com/mail/?shva=1#search/ipsec",
+      "http://mail.google.com/mail/?shva=1#search/ipsec/ee29ae66165d417",
+      "http://mail.google.com/mail/?shva=1#compose",
+      "<NEWTAB>",
+      "http://docs.google.com/",
+      "<NEWTAB>",
+      "http://calendar.google.com/",
+      "<NEWTAB>",
+      "http://maps.google.com/",
+      "http://maps.google.com/maps/mpl?moduleurl=http://earthquake.usgs.gov/eqcenter/mapplets/earthquakes.xml&ie=UTF8&ll=20,170&spn=140.625336,73.828125&t=k&z=2",
+      "http://maps.google.com/maps?f=q&hl=en&geocode=&q=1600+amphitheater+parkway,+mountain+view,+ca&ie=UTF8&z=13",
+      "<NEWTAB>",
+      "http://www.google.com/",
+      "http://www.google.com/search?hl=en&q=food&btnG=Google+Search",
+      "http://books.google.com/books?hl=en&q=food&um=1&ie=UTF-8&sa=N&tab=wp",
+      "http://images.google.com/images?hl=en&q=food&um=1&ie=UTF-8&sa=N&tab=pi",
+      "http://news.google.com/news?hl=en&q=food&um=1&ie=UTF-8&sa=N&tab=in",
+      "http://www.google.com/products?sa=N&tab=nf&q=food",
+      "<NEWTAB>",
+      "http://www.scoundrelspoint.com/polyhedra/shuttle/index.html",
+      "<PAUSE>",
+      "<NEWTAB>",
+      "http://ctho.ath.cx/toys/3d.html",
+      "<PAUSE>",
+      "<NEWTAB>",
+      "http://www.youtube.com/",
+      "http://www.youtube.com/results?search_query=funny&search_type=&aq=f",
+      "http://www.youtube.com/watch?v=GuMMfgWhm3g",
+      "<NEWTAB>",
+      "http://www.craigslist.com/",
+      "http://sfbay.craigslist.org/",
+      "http://sfbay.craigslist.org/apa/",
+      "http://sfbay.craigslist.org/sfc/apa/782398209.html",
+      "http://sfbay.craigslist.org/sfc/apa/782347795.html",
+      "http://sfbay.craigslist.org/sby/apa/782342791.html",
+      "http://sfbay.craigslist.org/sfc/apa/782344396.html",
+      "<NEWTAB>",
+      "http://www.whitehouse.gov/",
+      "http://www.whitehouse.gov/news/releases/2008/07/20080729.html",
+      "http://www.whitehouse.gov/infocus/afghanistan/",
+      "http://www.whitehouse.gov/infocus/africa/",
+      "<NEWTAB>",
+      "http://www.msn.com/",
+      "http://msn.foxsports.com/horseracing/story/8409670/Big-Brown-rebounds-in-Haskell-Invitational?MSNHPHMA",
+      "http://articles.moneycentral.msn.com/Investing/StockInvestingTrading/TheBiggestRiskToYourRetirement_SeriesHome.aspx",
+      "http://articles.moneycentral.msn.com/Investing/StockInvestingTrading/TheSmartWayToGetRich.aspx",
+      "http://articles.moneycentral.msn.com/Investing/ContrarianChronicles/TheFictionOfCorporateTransparency.aspx",
+      "<NEWTAB>",
+      "http://flickr.com/"
+      "http://flickr.com/explore/interesting/2008/03/18/",
+      "http://flickr.com/photos/chavals/2344906748/",
+      "http://flickr.com/photos/rosemary/2343058024/",
+      "http://flickr.com/photos/arbaa/2343235019/",
+      "<NEWTAB>",
+      "http://zh.wikipedia.org/wiki/%E6%B1%B6%E5%B7%9D%E5%A4%A7%E5%9C%B0%E9%9C%87",
+      "http://zh.wikipedia.org/wiki/5%E6%9C%8812%E6%97%A5",
+      "http://zh.wikipedia.org/wiki/5%E6%9C%8820%E6%97%A5",
+      "http://zh.wikipedia.org/wiki/%E9%A6%96%E9%A1%B5",
+      "<NEWTAB>",
+      "http://www.nytimes.com/pages/technology/index.html",
+      "http://pogue.blogs.nytimes.com/2008/07/17/a-candy-store-for-the-iphone/",
+      "http://www.nytimes.com/2008/07/21/technology/21pc.html?_r=1&ref=technology&oref=slogin",
+      "http://bits.blogs.nytimes.com/2008/07/19/a-wikipedian-challenge-convincing-arabic-speakers-to-write-in-arabic/",
+      "<NEWTAB>",
+      "http://www.amazon.com/exec/obidos/tg/browse/-/502394/ref=topnav_storetab_p",
+      "http://www.amazon.com/Panasonic-DMC-TZ5K-Digital-Optical-Stabilized/dp/B0011Z8CCG/ref=pd_ts_p_17?ie=UTF8&s=photo",
+      "http://www.amazon.com/Nikon-Coolpix-Digital-Vibration-Reduction/dp/B0012OI6HW/ref=pd_ts_p_24?ie=UTF8&s=photo",
+      "http://www.amazon.com/Digital-SLRs-Cameras-Photo/b/ref=sv_p_2?ie=UTF8&node=3017941",
+      "<NEWTAB>",
+      "http://www.boston.com/bigpicture/2008/07/californias_continuing_fires.html",
+      "http://www.boston.com/business/",
+      "http://www.boston.com/business/articles/2008/07/29/staples_has_a_games_plan/",
+      "http://www.boston.com/business/personalfinance/articles/2008/08/04/a_grim_forecast_for_heating_costs/",
+      "<NEWTAB>",
+      "http://arstechnica.com/",
+      "http://arstechnica.com/news.ars/post/20080721-this-years-e3-substance-over-styleand-far-from-dead.html",
+      "http://arstechnica.com/news.ars/post/20080729-ifpi-italian-police-take-down-italian-bittorrent-tracker.html",
+      "http://arstechnica.com/news.ars/post/20080804-congress-wants-privacy-answers-from-google-ms-aol.html",
+      "<NEWTAB>",
+      "http://finance.google.com/finance?q=NASDAQ:AAPL",
+      "http://finance.google.com/finance?q=GOOG&hl=en",
+      "<NEWTAB>",
+      "http://blog.wired.com/underwire/2008/07/futurama-gets-m.html",
+      "http://blog.wired.com/cars/2008/07/gas-prices-hit.html",
+      "<NEWTAB>",
+      "http://del.icio.us/popular/programming",
+      "http://del.icio.us/popular/",
+      "http://del.icio.us/tag/",
+      "<NEWTAB>",
+      "http://gadgets.boingboing.net/2008/07/21/boom-computing.html",
+      "http://3533.spreadshirt.com/us/US/Shop/",
+      "<NEWTAB>",
+      "http://www.autoblog.com/",
+      "http://www.autoblog.com/2008/07/21/audi-introduces-the-next-mmi/",
+      "http://www.autoblog.com/categories/auto-types/",
+      "http://www.autoblog.com/category/sports/",
+      "<NEWTAB>",
+      "http://www.wikipedia.org/",
+      "http://en.wikipedia.org/wiki/Main_Page",
+      "http://fr.wikipedia.org/wiki/Accueil",
+      "http://de.wikipedia.org/wiki/Hauptseite",
+      "http://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8",
+      "http://it.wikipedia.org/wiki/Pagina_principale",
+      "http://nl.wikipedia.org/wiki/Hoofdpagina",
+      "http://pt.wikipedia.org/wiki/P%C3%A1gina_principal",
+      "http://es.wikipedia.org/wiki/Portada",
+      "http://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0",
+      "<NEWTAB>",
+      "http://www.google.com/translate_t?hl=en&text=This%20Is%20A%20Test%20Of%20missspellingsdfdf&sl=en&tl=ja",
+    };
+
+    // Record the initial CommitCharge.  This is a system-wide measurement,
+    // so if other applications are running, they can create variance in this
+    // test.
+    size_t start_size = GetSystemCommitCharge();
+
+    // Cycle through the URLs.
+    scoped_ptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
+    scoped_ptr<TabProxy> tab(window->GetActiveTab());
+    int expected_tab_count = 1;
+    for (unsigned counter = 0; counter < arraysize(urls); ++counter) {
+      std::string url = urls[counter];
+
+      if (url == "<PAUSE>") {  // Special command to delay on this page
+        Sleep(2000);
+        continue;
+      }
+
+      if (url == "<NEWTAB>") {  // Special command to create a new tab
+        if (++counter >= arraysize(urls))
+          continue;  // Newtab was specified at end of list.  ignore.
+
+        url = urls[counter];
+        if (GetTabCount() < num_target_tabs) {
+          EXPECT_TRUE(window->AppendTab(GURL(url)));
+          expected_tab_count++;
+          WaitUntilTabCount(expected_tab_count);
+          tab.reset(window->GetActiveTab());
+          continue;
+        }
+
+        int tab_index = counter % num_target_tabs;  // A pseudo-random tab.
+        tab.reset(window->GetTab(tab_index));
+      }
+
+      tab->NavigateToURL(GURL(urls[counter]));
+    }
+    size_t stop_size = GetSystemCommitCharge();
+
+    PrintResults(test_name, stop_size - start_size);
+  }
+
+  void PrintResults(const wchar_t* test_name, size_t commit_size) {
+    PrintMemoryUsageInfo(test_name);
+    wprintf(L"%s_commit_charge_kb = %d\n", test_name, commit_size / 1024);
+  }
+
+  void PrintIOPerfInfo(const wchar_t* test_name) {
+    printf("\n");
+    BrowserProcessFilter chrome_filter(user_data_dir_);
+    process_util::NamedProcessIterator
+        chrome_process_itr(chrome::kBrowserProcessExecutableName,
+                           &chrome_filter);
+
+    const PROCESSENTRY32* chrome_entry;
+    while (chrome_entry = chrome_process_itr.NextProcessEntry()) {
+      uint32 pid = chrome_entry->th32ProcessID;
+      HANDLE process_handle = OpenProcess(PROCESS_QUERY_INFORMATION,
+                                          false,
+                                          pid);
+      if (process_handle == NULL) {
+        wprintf(L"Error opening process %d: %d\n", pid, GetLastError());
+        continue;
+      }
+
+      scoped_ptr<process_util::ProcessMetrics> process_metrics;
+      IO_COUNTERS io_counters;
+      process_metrics.reset(
+          process_util::ProcessMetrics::CreateProcessMetrics(process_handle));
+      ZeroMemory(&io_counters, sizeof(io_counters));
+
+      if (process_metrics.get()->GetIOCounters(&io_counters)) {
+        wchar_t* browser_name = L"browser";
+        wchar_t* render_name = L"render";
+        wchar_t* chrome_name;
+        if (pid == chrome_filter.browser_process_id()) {
+          chrome_name = browser_name;
+        } else {
+          chrome_name = render_name;
+        }
+
+        // print out IO performance
+        wprintf(L"%s_%s_read_op = %d\n",
+                test_name, chrome_name, io_counters.ReadOperationCount);
+        wprintf(L"%s_%s_write_op = %d\n",
+                test_name, chrome_name, io_counters.WriteOperationCount);
+        wprintf(L"%s_%s_other_op = %d\n",
+                test_name, chrome_name, io_counters.OtherOperationCount);
+        wprintf(L"%s_%s_read_byte = %d K\n",
+                test_name, chrome_name, io_counters.ReadTransferCount / 1024);
+        wprintf(L"%s_%s_write_byte = %d K\n",
+                test_name, chrome_name, io_counters.WriteTransferCount / 1024);
+        wprintf(L"%s_%s_other_byte = %d K\n",
+                test_name, chrome_name, io_counters.OtherTransferCount / 1024);
+      }
+    }
+  }
+
+  void PrintMemoryUsageInfo(const wchar_t* test_name) {
+    printf("\n");
+    BrowserProcessFilter chrome_filter(user_data_dir_);
+    process_util::NamedProcessIterator
+        chrome_process_itr(chrome::kBrowserProcessExecutableName,
+                           &chrome_filter);
+
+    size_t browser_virtual_size = 0;
+    size_t browser_working_set_size = 0;
+    size_t virtual_size = 0;
+    size_t working_set_size = 0;
+    size_t num_chrome_processes = 0;
+    const PROCESSENTRY32* chrome_entry;
+    while (chrome_entry = chrome_process_itr.NextProcessEntry()) {
+      uint32 pid = chrome_entry->th32ProcessID;
+      size_t peak_virtual_size;
+      size_t current_virtual_size;
+      size_t peak_working_set_size;
+      size_t current_working_set_size;
+      if (GetMemoryInfo(pid, &peak_virtual_size, &current_virtual_size,
+                        &peak_working_set_size, &current_working_set_size)) {
+        if (pid == chrome_filter.browser_process_id()) {
+          browser_virtual_size = current_virtual_size;
+          browser_working_set_size = current_working_set_size;
+        }
+        virtual_size += current_virtual_size;
+        working_set_size += current_working_set_size;
+        num_chrome_processes++;
+      }
+    }
+    wprintf(L"%s_browser_vm_final_kb = %d\n", test_name,
+                                           browser_virtual_size / 1024);
+    wprintf(L"%s_browser_ws_final_kb = %d\n", test_name,
+                                           browser_working_set_size / 1024);
+    wprintf(L"%s_memory_vm_final_kb = %d\n", test_name,
+                                          virtual_size / 1024);
+    wprintf(L"%s_memory_ws_final_kb = %d\n", test_name,
+                                          working_set_size / 1024);
+    wprintf(L"%s_processes = %d\n", test_name, num_chrome_processes);
+  }
+
+ private:
+  std::wstring user_data_dir_;
+};
+
+class MemoryReferenceTest : public MemoryTest {
+ public:
+  // override the browser directory that is used by UITest::SetUp to cause it
+  // to use the reference build instead.
+  void SetUp() {
+    std::wstring dir;
+    PathService::Get(chrome::DIR_TEST_TOOLS, &dir);
+    file_util::AppendToPath(&dir, L"reference_build");
+    file_util::AppendToPath(&dir, L"chrome");
+    browser_directory_ = dir;
+    UITest::SetUp();
+  }
+
+  void RunTest(const wchar_t* test_name, int num_target_tabs) {
+    std::wstring pages, timings;
+    MemoryTest::RunTest(test_name, num_target_tabs);
+  }
+};
+
+}  // namespace
+
+TEST_F(MemoryTest, SingleTabTest) {
+  RunTest(L"OneTabTest", 1);
+}
+
+TEST_F(MemoryTest, FiveTabTest) {
+  RunTest(L"FiveTabTest", 5);
+}
+
+TEST_F(MemoryTest, TwelveTabTest) {
+  RunTest(L"TwelveTabTest", 12);
+}
diff --git a/chrome/test/memory_test/memory_test.vcproj b/chrome/test/memory_test/memory_test.vcproj
new file mode 100644
index 0000000..50a20c5
--- /dev/null
+++ b/chrome/test/memory_test/memory_test.vcproj
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="8.00"

+	Name="memory_test"

+	ProjectGUID="{A5F831FD-9B9C-4FEF-9FBA-554817B734CE}"

+	RootNamespace="memory_test"

+	>

+	<Platforms>

+		<Platform

+			Name="Win32"

+		/>

+	</Platforms>

+	<ToolFiles>

+	</ToolFiles>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			ConfigurationType="1"

+			InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\..\tools\build\win\precompiled_wtl.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalDependencies="winmm.lib"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCManifestTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCAppVerifierTool"

+			/>

+			<Tool

+				Name="VCWebDeploymentTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			ConfigurationType="1"

+			InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;..\..\tools\build\win\unit_test.vsprops;..\..\tools\build\win\ui_test.vsprops;..\..\tools\build\win\test_memory_usage.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalDependencies="winmm.lib"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCManifestTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCAppVerifierTool"

+			/>

+			<Tool

+				Name="VCWebDeploymentTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Common"

+			>

+			<File

+				RelativePath="..\..\tools\build\win\precompiled_wtl.cc"

+				>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						UsePrecompiledHeader="1"

+					/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\..\tools\build\win\precompiled_wtl.h"

+				>

+			</File>

+			<File

+				RelativePath="..\ui\run_all_unittests.cc"

+				>

+			</File>

+			<File

+				RelativePath="..\test_file_util.cc"

+				>

+			</File>

+			<File

+				RelativePath="..\test_file_util.h"

+				>

+			</File>

+			<File

+				RelativePath="..\testing_browser_process.h"

+				>

+			</File>

+			<File

+				RelativePath="..\ui\ui_test.cc"

+				>

+			</File>

+			<File

+				RelativePath="..\ui\ui_test.h"

+				>

+			</File>

+			<File

+				RelativePath="..\ui\ui_test_suite.cc"

+				>

+			</File>

+		</Filter>

+		<Filter

+			Name="MemoryUsage"

+			>

+			<File

+				RelativePath="..\perf\mem_usage.cc"

+				>

+			</File>

+			<File

+				RelativePath="..\perf\mem_usage.h"

+				>

+			</File>

+		</Filter>

+		<Filter

+			Name="TestMemeory"

+			>

+			<File

+				RelativePath=".\memory_test.cc"

+				>

+			</File>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/chrome/test/page_cycler/page_cycler_test.cc b/chrome/test/page_cycler/page_cycler_test.cc
index b9a77bd..39b10b5 100644
--- a/chrome/test/page_cycler/page_cycler_test.cc
+++ b/chrome/test/page_cycler/page_cycler_test.cc
@@ -115,7 +115,7 @@
 
   void PrintIOPerfInfo(const wchar_t* test_name) {
     printf("\n");
-    BrowserProcessFilter chrome_filter;
+    BrowserProcessFilter chrome_filter(L"");
     process_util::NamedProcessIterator
         chrome_process_itr(chrome::kBrowserProcessExecutableName,
                            &chrome_filter);
@@ -162,7 +162,7 @@
 
   void PrintMemoryUsageInfo(const wchar_t* test_name) {
     printf("\n");
-    BrowserProcessFilter chrome_filter;
+    BrowserProcessFilter chrome_filter(L"");
     process_util::NamedProcessIterator
         chrome_process_itr(chrome::kBrowserProcessExecutableName,
                            &chrome_filter);
diff --git a/chrome/test/perf/mem_usage.cc b/chrome/test/perf/mem_usage.cc
index c8ec78c..369295e1 100644
--- a/chrome/test/perf/mem_usage.cc
+++ b/chrome/test/perf/mem_usage.cc
@@ -41,7 +41,6 @@
                    size_t *current_virtual_size,
                    size_t *peak_working_set_size,
                    size_t *current_working_set_size) {
-
   if (!peak_virtual_size || !current_virtual_size)
     return false;
 
@@ -67,14 +66,25 @@
   return result;
 }
 
+size_t GetSystemCommitCharge() {
+  // Get the System Page Size.
+  SYSTEM_INFO system_info;
+  GetSystemInfo(&system_info);
+
+  PERFORMANCE_INFORMATION info;
+  if (GetPerformanceInfo(&info, sizeof(info)))
+    return info.CommitTotal * system_info.dwPageSize;
+  return -1;
+}
+
 void PrintChromeMemoryUsageInfo() {
   printf("\n");
-  BrowserProcessFilter chrome_filter;
+  BrowserProcessFilter chrome_filter(L"");
   process_util::NamedProcessIterator
       chrome_process_itr(chrome::kBrowserProcessExecutableName, &chrome_filter);
 
   const PROCESSENTRY32* chrome_entry;
-  while(chrome_entry = chrome_process_itr.NextProcessEntry()) {
+  while (chrome_entry = chrome_process_itr.NextProcessEntry()) {
     uint32 pid = chrome_entry->th32ProcessID;
     size_t peak_virtual_size;
     size_t current_virtual_size;
diff --git a/chrome/test/perf/mem_usage.h b/chrome/test/perf/mem_usage.h
index 940a0d1..467bb94a 100644
--- a/chrome/test/perf/mem_usage.h
+++ b/chrome/test/perf/mem_usage.h
@@ -59,6 +59,10 @@
                    size_t *peak_working_set_size,
                    size_t *current_working_set_size);
 
+// Get the number of bytes currently committed by the system.
+// Returns -1 on failure.
+size_t GetSystemCommitCharge();
+
 // Get and print memory usage information for running chrome processes.
 void PrintChromeMemoryUsageInfo();
-#endif // CHROME_TEST_PERF_MEM_USAGE_H__
+#endif  // CHROME_TEST_PERF_MEM_USAGE_H__
diff --git a/chrome/test/ui/ui_test.cc b/chrome/test/ui/ui_test.cc
index 2d7813d..cd439118 100644
--- a/chrome/test/ui/ui_test.cc
+++ b/chrome/test/ui/ui_test.cc
@@ -320,7 +320,7 @@
 }
 
 void UITest::CleanupAppProcesses() {
-  BrowserProcessFilter filter;
+  BrowserProcessFilter filter(L"");
 
   // Make sure that no instances of the browser remain.
   const int kExitTimeoutMs = 5000;
@@ -408,7 +408,7 @@
 
 /*static*/
 int UITest::GetBrowserProcessCount() {
-  BrowserProcessFilter filter;
+  BrowserProcessFilter filter(L"");
   return process_util::GetProcessCount(chrome::kBrowserProcessExecutableName,
                                        &filter);
 }