diff options
author | sky <sky@chromium.org> | 2015-07-01 14:38:28 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-07-01 21:38:50 +0000 |
commit | b98685d8a6254479c846441ca8d7acfc374abf67 (patch) | |
tree | c771814ebe43470c0151a38158fa60ce97156656 /chrome/browser/private_working_set_snapshot_win.cc | |
parent | 9e6b4b947c12a59a7c57df1b08801270497ce90a (diff) | |
download | chromium_src-b98685d8a6254479c846441ca8d7acfc374abf67.zip chromium_src-b98685d8a6254479c846441ca8d7acfc374abf67.tar.gz chromium_src-b98685d8a6254479c846441ca8d7acfc374abf67.tar.bz2 |
Revert of Make task manager memory data more efficient and meaningful. (patchset #16 id:300001 of https://codereview.chromium.org/1181263005/)
Reason for revert:
This appears to have triggered a unit test failure on the vista bot.
https://build.chromium.org/p/chromium.win/builders/Vista%20Tests%20%281%29/builds/57386
output:
(view as text)
PrivateWorkingSetSnapshotWinTest.FindPidSelfTest (run #1):
[ RUN ] PrivateWorkingSetSnapshotWinTest.FindPidSelfTest
c:\b\build\slave\win_builder\build\src\chrome\browser\private_working_set_snapshot_win_unittest.cc(32): error: Expected: (private_ws) > (2000000u), actual: 0 vs 2000000
c:\b\build\slave\win_builder\build\src\chrome\browser\private_working_set_snapshot_win_unittest.cc(50): error: Expected: (private_ws3) > (private_ws2 + alloc_size / 2), actual: 0 vs 5000000
GetPrivateWorkingSet should increase as we allocate more memory
[ FAILED ] PrivateWorkingSetSnapshotWinTest.FindPidSelfTest (78 ms)
PrivateWorkingSetSnapshotWinTest.FindPidSelfTest (run #2):
[ RUN ] PrivateWorkingSetSnapshotWinTest.FindPidSelfTest
c:\b\build\slave\win_builder\build\src\chrome\browser\private_working_set_snapshot_win_unittest.cc(32): error: Expected: (private_ws) > (2000000u), actual: 0 vs 2000000
c:\b\build\slave\win_builder\build\src\chrome\browser\private_working_set_snapshot_win_unittest.cc(50): error: Expected: (private_ws3) > (private_ws2 + alloc_size / 2), actual: 0 vs 5000000
GetPrivateWorkingSet should increase as we allocate more memory
[ FAILED ] PrivateWorkingSetSnapshotWinTest.FindPidSelfTest (47 ms)
PrivateWorkingSetSnapshotWinTest.FindPidSelfTest (run #3):
[ RUN ] PrivateWorkingSetSnapshotWinTest.FindPidSelfTest
c:\b\build\slave\win_builder\build\src\chrome\browser\private_working_set_snapshot_win_unittest.cc(32): error: Expected: (private_ws) > (2000000u), actual: 0 vs 2000000
c:\b\build\slave\win_builder\build\src\chrome\browser\private_working_set_snapshot_win_unittest.cc(50): error: Expected: (private_ws3) > (private_ws2 + alloc_size / 2), actual: 0 vs 5000000
GetPrivateWorkingSet should increase as we allocate more memory
[ FAILED ] PrivateWorkingSetSnapshotWinTest.FindPidSelfTest (47 ms)
PrivateWorkingSetSnapshotWinTest.FindPidSelfTest (run #4):
[ RUN ] PrivateWorkingSetSnapshotWinTest.FindPidSelfTest
c:\b\build\slave\win_builder\build\src\chrome\browser\private_working_set_snapshot_win_unittest.cc(32): error: Expected: (private_ws) > (2000000u), actual: 0 vs 2000000
c:\b\build\slave\win_builder\build\src\chrome\browser\private_working_set_snapshot_win_unittest.cc(50): error: Expected: (private_ws3) > (private_ws2 + alloc_size / 2), actual: 0 vs 5000000
GetPrivateWorkingSet should increase as we allocate more memory
[ FAILED ] PrivateWorkingSetSnapshotWinTest.FindPidSelfTest (47 ms)
Original issue's description:
> Make task manager memory data more efficient and meaningful.
>
> Chrome's default memory column is quite expensive to calculate. The
> Windows version of ProcessMetrics::GetWorkingSetKBytes uses QueryWorkingSet
> which returns information for every page in the process. Generating and
> copying this data is expensive enough that it can lead to 100+ ms hitches
> in scrolling, which also means that it is consuming 10% of a core (100 ms
> for every per-second update). That is with about 20 tabs open and the cost
> increases proportionally with more tabs. See bug 494210
>
> Chrome's default memory column also does not display the best possible
> number. Because it includes shareable-but-not-shared memory it means that
> renderer code goes from being counted when one tab is open to being not
> count when two tabs are open. This causes confusion. Proportional Set Size
> could avoid this confusion but is non-standard for Windows. Private working
> set is a better choice because it has a clear meaning and is a standard
> memory column in task manager and process explorer. See bug 484433
>
> This change adds a RefreshPhysicalMemoryFromWorkingSetSnapshot step to
> TaskManagerModel::Refresh. After the old data has been thrown away the
> RefreshPhysicalMemoryFromWorkingSetSnapshot function uses Pdh to
> retrieve private working set data for all chrome processes. Then when
> TaskManagerModel::GetPhysicalMemory is called it will almost always find
> that values.is_physical_memory_valid is already true. Because Pdh retrieves
> all private working sets in one call, from the private-to-Windows memory
> bookkeeping data, this is much faster than calculating working sets for
> each process individually and the cost is mostly independent of the number
> of processes.
>
> Therefore the speedup from using Pdh increases with more tabs. If the user
> has one small tab open then Pdh is slightly faster. With three tabs open
> Pdh is significantly faster. With six tabs (eight processes) Pdh is nine
> times faster than using QueryWorkingSet (0.18 ms per process versus 1.6 ms
> per process).
>
> GetPhysicalMemory has been modified to subtract shareable from the
> physical_memory instead of shared so that it also calculates private
> working set, for consistency. This change is a NOP on OSX because shared
> and shareable are both always zero (see GetCommittedAndWorkingSetKBytes in
> process_metrics_mac.cc).
>
> In the cases where Pdh fails or a new chrome process is created between
> RefreshPhysicalMemoryFromWorkingSetSnapshot and GetPhysicalMemory the
> GetPhysicalMemory calculations will be used. The results typically differ by
> less than 0.5%. Alternating between the two methods on each refresh shows no
> significant change.
>
> Pdh supports retrieving private working set data on Vista and above. On
> Windows XP the code will fall-back to using the old method.
>
> Pdh will return private WS data for all chrome* processes, so canary and
> stable will see each other's processes, but
> RefreshPhysicalMemoryFromWorkingSetSnapshot will ignore unrelated processes.
> Processes with names like 'chromeWidget.exe' will also be listed and will
> also be ignored. This does not measurably affect performance.
>
> R=nick@chromium.org,jschuh@chromium.org,rsesek@chromium.org,thakis@chromium.org
> BUG=484433,494210
>
> Committed: https://crrev.com/f66d1ecf0cd7426393088c91f2af78ff1889bab4
> Cr-Commit-Position: refs/heads/master@{#337096}
TBR=nick@chromium.org,jschuh@chromium.org,rsesek@chromium.org,thakis@chromium.org,brucedawson@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=484433,494210
Review URL: https://codereview.chromium.org/1219233002
Cr-Commit-Position: refs/heads/master@{#337117}
Diffstat (limited to 'chrome/browser/private_working_set_snapshot_win.cc')
-rw-r--r-- | chrome/browser/private_working_set_snapshot_win.cc | 160 |
1 files changed, 0 insertions, 160 deletions
diff --git a/chrome/browser/private_working_set_snapshot_win.cc b/chrome/browser/private_working_set_snapshot_win.cc deleted file mode 100644 index 56fb568..0000000 --- a/chrome/browser/private_working_set_snapshot_win.cc +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/private_working_set_snapshot.h" - -#include <pdh.h> -#include <pdhmsg.h> - -#include <algorithm> - -#include "base/numerics/safe_conversions.h" -#include "base/win/windows_version.h" - -// Link pdh.lib (import library for pdh.dll) whenever this file is linked in. -#pragma comment(lib, "pdh.lib") - -PrivateWorkingSetSnapshot::PrivateWorkingSetSnapshot() { - // The Pdh APIs are supported on Windows XP, but the "Working Set - Private" - // counter that PrivateWorkingSetSnapshot depends on is not defined until - // Windows Vista. Early-out to avoid wasted effort. All queries will return - // zero and will have to use the fallback calculations. - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return; - - // Create a Pdh query - PDH_HQUERY query_handle; - if (PdhOpenQuery(NULL, NULL, &query_handle) != ERROR_SUCCESS) { - return; - } - - query_handle_.Set(query_handle); -} - -PrivateWorkingSetSnapshot::~PrivateWorkingSetSnapshot() { -} - -void PrivateWorkingSetSnapshot::AddToMonitorList( - const std::string& process_name) { - if (!query_handle_.IsValid()) - return; - - // Create the magic strings that will return a list of process IDs and a list - // of private working sets. The 'process_name' variable should be something - // like "chrome". The '*' character indicates that we want records for all - // processes whose names start with process_name - all chrome processes, but - // also all 'chrome_editor.exe' processes or other matching names. The excess - // information is unavoidable but harmless. - std::string process_id_query = "\\Process(" + process_name + "*)\\ID Process"; - std::string private_ws_query = - "\\Process(" + process_name + "*)\\Working Set - Private"; - - // Add the two counters to the query. - PdhCounterPair new_counters; - if (PdhAddCounterA(query_handle_.Get(), process_id_query.c_str(), NULL, - &new_counters.process_id_handle) != ERROR_SUCCESS) { - return; - } - - // If adding the second counter fails then we should remove the first one. - if (PdhAddCounterA(query_handle_.Get(), private_ws_query.c_str(), NULL, - &new_counters.private_ws_handle) != ERROR_SUCCESS) { - PdhRemoveCounter(new_counters.process_id_handle); - } - - // Record the pair of counter query handles so that we can query them later. - counter_pairs_.push_back(new_counters); -} - -void PrivateWorkingSetSnapshot::Sample() { - if (counter_pairs_.empty()) - return; - - // Destroy all previous data. - records_.resize(0); - // Record the requested data into PDH's internal buffers. - if (PdhCollectQueryData(query_handle_.Get()) != ERROR_SUCCESS) - return; - - for (auto& counter_pair : counter_pairs_) { - // Find out how much space is required for the two counter arrays. - // A return code of PDH_MORE_DATA indicates that we should call again with - // the buffer size returned. - DWORD buffer_size1 = 0; - DWORD item_count1 = 0; - // Process IDs should be retrieved as PDH_FMT_LONG - if (PdhGetFormattedCounterArray(counter_pair.process_id_handle, - PDH_FMT_LONG, &buffer_size1, &item_count1, - nullptr) != PDH_MORE_DATA) - continue; - if (buffer_size1 == 0 || item_count1 == 0) - continue; - - DWORD buffer_size2 = 0; - DWORD item_count2 = 0; - // Working sets should be retrieved as PDH_FMT_LARGE (LONGLONG) - // Note that if this second call to PdhGetFormattedCounterArray with the - // buffer size and count variables being zero is omitted then the PID and - // working-set results are not reliably correlated. - if (PdhGetFormattedCounterArray(counter_pair.private_ws_handle, - PDH_FMT_LARGE, &buffer_size2, &item_count2, - nullptr) != PDH_MORE_DATA) - continue; - - // It is not clear whether Pdh guarantees that the two counters in the same - // query will execute atomically - if they will see the same set of - // processes. If they do not then the correspondence between "ID Process" - // and "Working Set - Private" is lost and we have to discard these results. - // In testing these values have always matched. If this check fails then - // the old per-process memory calculations will be used instead. - if (buffer_size1 != buffer_size2 || item_count1 != item_count2) - continue; - - // Allocate enough space for the results of both queries. - std::vector<char> buffer(buffer_size1 * 2); - // Retrieve the process ID data. - auto process_id_data = - reinterpret_cast<PDH_FMT_COUNTERVALUE_ITEM*>(&buffer[0]); - if (PdhGetFormattedCounterArray(counter_pair.process_id_handle, - PDH_FMT_LONG, &buffer_size1, &item_count1, - process_id_data) != ERROR_SUCCESS) - continue; - // Retrieve the private working set data. - auto private_ws_data = - reinterpret_cast<PDH_FMT_COUNTERVALUE_ITEM*>(&buffer[buffer_size1]); - if (PdhGetFormattedCounterArray(counter_pair.private_ws_handle, - PDH_FMT_LARGE, &buffer_size1, &item_count1, - private_ws_data) != ERROR_SUCCESS) - continue; - - // Make room for the new set of records. - size_t start_offset = records_.size(); - records_.resize(start_offset + item_count1); - - for (DWORD i = 0; i < item_count1; ++i) { - records_[start_offset + i].process_id = - process_id_data[i].FmtValue.longValue; - // Integer overflow can happen here if a 32-bit process is monitoring a - // 64-bit process so we do a saturated_cast. - records_[start_offset + i].private_ws = - base::saturated_cast<size_t>(private_ws_data[i].FmtValue.largeValue); - } - } - - // The results will include all processes that match the passed in name, - // regardless of whether they are spawned by the calling process. - // The results must be sorted by process ID for efficient lookup. - std::sort(records_.begin(), records_.end()); -} - -size_t PrivateWorkingSetSnapshot::GetPrivateWorkingSet( - base::ProcessId process_id) const { - // Do a binary search for the requested process ID and return the working set - // if found. - auto p = std::lower_bound(records_.begin(), records_.end(), process_id); - if (p != records_.end() && p->process_id == process_id) - return p->private_ws; - - return 0; -} |