diff options
author | peria@chromium.org <peria@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-01 07:08:21 +0000 |
---|---|---|
committer | peria@chromium.org <peria@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-01 07:08:21 +0000 |
commit | 0d9b30458af1e2c7c4282f876e6556af3ede4c99 (patch) | |
tree | 29601215a86f6d1973ef7919dafe370d4497e9bd | |
parent | 7361110ac1e6673f9a92c73bae1c0505fcf74ac1 (diff) | |
download | chromium_src-0d9b30458af1e2c7c4282f876e6556af3ede4c99.zip chromium_src-0d9b30458af1e2c7c4282f876e6556af3ede4c99.tar.gz chromium_src-0d9b30458af1e2c7c4282f876e6556af3ede4c99.tar.bz2 |
Add information of V8 heap memories, in chrome://memory-internals
BUG=168642
TEST=Manual
Review URL: https://chromiumcodereview.appspot.com/17449003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@209373 0039d316-1c4b-4281-b951-d872f2087c98
5 files changed, 173 insertions, 47 deletions
diff --git a/chrome/browser/resources/memory_internals/memory_internals.js b/chrome/browser/resources/memory_internals/memory_internals.js index 233feb8..c448a6b 100644 --- a/chrome/browser/resources/memory_internals/memory_internals.js +++ b/chrome/browser/resources/memory_internals/memory_internals.js @@ -64,9 +64,15 @@ var MainView = (function() { case 'process-info': value = process['type'] + '<br>' + process['titles'].join('<br>'); break; - case 'process-memory': + case 'process-memory-private': value = process['memory_private']; break; + case 'process-memory-v8': + if (process['v8_alloc'] !== undefined) { + value = 'Used : ' + process['v8_used'] + '<br>' + + 'Allocated : ' + process['v8_alloc']; + } + break; } var col = row.insertCell(-1); col.innerHTML = value; diff --git a/chrome/browser/resources/memory_internals/snapshot_view.css b/chrome/browser/resources/memory_internals/snapshot_view.css index 3b24f73..4e57b21 100644 --- a/chrome/browser/resources/memory_internals/snapshot_view.css +++ b/chrome/browser/resources/memory_internals/snapshot_view.css @@ -17,11 +17,14 @@ } #snapshot-view .header th { - border-bottom: 1px solid rgb(181, 198, 222); padding: 0.35em 0.5em 0; vertical-align: bottom; } +#snapshot-view .bottom th { + border-bottom: 1px solid rgb(181, 198, 222); +} + #snapshot-view .process-id { text-align: right; width: 4em; @@ -33,8 +36,18 @@ #snapshot-view .process-memory { border-left: 1px solid rgb(181, 198, 222); + width: 16em; +} + +#snapshot-view .process-memory-private { + border-left: 1px solid rgb(181, 198, 222); + text-align: right; + width: 6em; +} + +#snapshot-view .process-memory-v8 { text-align: right; - width: 7em; + width: 10em; } #snapshot-view #process-template { diff --git a/chrome/browser/resources/memory_internals/snapshot_view.html b/chrome/browser/resources/memory_internals/snapshot_view.html index 0a5ecb6..43d041d 100644 --- a/chrome/browser/resources/memory_internals/snapshot_view.html +++ b/chrome/browser/resources/memory_internals/snapshot_view.html @@ -7,11 +7,15 @@ <table id="snapshot-view"> <tr class="header"> - <th class="process-id">PID - <th class="process-info">Name - <th class="process-memory">Private Memory [KB] + <th rowspan="2" class="process-id">PID + <th rowspan="2" class="process-info">Name + <th colspan="2" class="process-memory">Memory [KB] + <tr class="header bottom"> + <th class="process-memory-private">Private + <th class="process-memory-v8">V8 <tr id="process-template"> <td class="process-id"> <td class="process-info"> - <td class="process-memory"> + <td class="process-memory-private"> + <td class="process-memory-v8"> </table> diff --git a/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.cc b/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.cc index d55e6a8..accb3a5 100644 --- a/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.cc +++ b/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.cc @@ -4,42 +4,38 @@ #include "chrome/browser/ui/webui/memory_internals/memory_internals_proxy.h" +#include <set> #include <string> #include <vector> #include "base/bind.h" #include "base/strings/string16.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" #include "base/sys_info.h" #include "base/values.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/defaults.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/extension_system.h" #include "chrome/browser/memory_details.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/renderer_host/chrome_render_message_filter.h" +#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" #include "chrome/browser/ui/webui/memory_internals/memory_internals_handler.h" -#include "chrome/common/extensions/extension.h" -#include "chrome/common/extensions/extension_set.h" -#include "content/public/browser/url_data_source.h" +#include "chrome/common/chrome_notification_types.h" +#include "chrome/common/render_messages.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" -#include "grit/chromium_strings.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/webui/jstemplate_builder.h" -#include "ui/webui/web_ui_util.h" using content::BrowserThread; namespace { -class BrowserProcessDetails : public MemoryDetails { +class ProcessDetails : public MemoryDetails { public: typedef base::Callback<void(const ProcessData&)> DataCallback; - explicit BrowserProcessDetails(const DataCallback& callback) + explicit ProcessDetails(const DataCallback& callback) : callback_(callback) {} + // MemoryDetails: virtual void OnDetailsAvailable() OVERRIDE { const std::vector<ProcessData>& browser_processes = processes(); // [0] means Chrome. @@ -47,16 +43,75 @@ class BrowserProcessDetails : public MemoryDetails { } private: - virtual ~BrowserProcessDetails() {} + virtual ~ProcessDetails() {} DataCallback callback_; - DISALLOW_COPY_AND_ASSIGN(BrowserProcessDetails); + DISALLOW_COPY_AND_ASSIGN(ProcessDetails); }; } // namespace -MemoryInternalsProxy::MemoryInternalsProxy() {} +class RendererDetails : public content::NotificationObserver { + public: + typedef base::Callback<void(const base::ProcessId pid, + const size_t v8_allocated, + const size_t v8_used)> V8DataCallback; + + explicit RendererDetails(const V8DataCallback& callback) + : callback_(callback) { + registrar_.Add(this, chrome::NOTIFICATION_RENDERER_V8_HEAP_STATS_COMPUTED, + content::NotificationService::AllSources()); + } + virtual ~RendererDetails() {} + + void Request() { + for (std::set<content::WebContents*>::iterator iter = web_contents_.begin(); + iter != web_contents_.end(); ++iter) + (*iter)->GetRenderViewHost()->Send(new ChromeViewMsg_GetV8HeapStats); + } + void AddWebContents(content::WebContents* content) { + web_contents_.insert(content); + } + void Clear() { + web_contents_.clear(); + } + void RemoveWebContents() { + // We don't have to detect which content is the caller of this method. + if (!web_contents_.empty()) + web_contents_.erase(web_contents_.begin()); + } + int IsClean() { + return web_contents_.empty(); + } + + private: + // NotificationObserver: + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE { + const base::ProcessId* pid = + content::Source<const base::ProcessId>(source).ptr(); + const ChromeRenderMessageFilter::V8HeapStatsDetails* v8_heap = + content::Details<const ChromeRenderMessageFilter::V8HeapStatsDetails>( + details).ptr(); + callback_.Run(*pid, + v8_heap->v8_memory_allocated(), + v8_heap->v8_memory_used()); + } + + V8DataCallback callback_; + content::NotificationRegistrar registrar_; + std::set<content::WebContents*> web_contents_; // This class does not own + + DISALLOW_COPY_AND_ASSIGN(RendererDetails); +}; + +MemoryInternalsProxy::MemoryInternalsProxy() + : information_(new base::DictionaryValue()), + renderer_details_(new RendererDetails( + base::Bind(&MemoryInternalsProxy::OnV8MemoryUpdate, this))) { +} void MemoryInternalsProxy::Attach(MemoryInternalsHandler* handler) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -71,7 +126,7 @@ void MemoryInternalsProxy::Detach() { void MemoryInternalsProxy::GetInfo(const base::ListValue* list) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - scoped_refptr<BrowserProcessDetails> browsers(new BrowserProcessDetails( + scoped_refptr<ProcessDetails> browsers(new ProcessDetails( base::Bind(&MemoryInternalsProxy::OnDetailsAvailable, this))); browsers->StartFetch(MemoryDetails::SKIP_USER_METRICS); } @@ -86,42 +141,80 @@ void MemoryInternalsProxy::UpdateUIOnUIThread(const string16& update) { handler_->OnUpdate(update); } +void MemoryInternalsProxy::OnV8MemoryUpdate(const base::ProcessId pid, + const size_t v8_allocated, + const size_t v8_used) { + base::ListValue* processes; + if (!information_->GetList("processes", &processes)) + return; + + const size_t size = processes->GetSize(); + for (size_t i = 0; i < size; ++i) { + base::DictionaryValue* process; + processes->GetDictionary(i, &process); + int id; + if (!process->GetInteger("pid", &id) || id != static_cast<int>(pid)) + continue; + process->SetInteger("v8_alloc", v8_allocated); + process->SetInteger("v8_used", v8_used); + break; + } + + renderer_details_->RemoveWebContents(); + if (renderer_details_->IsClean()) + CallJavaScriptFunctionOnUIThread("g_main_view.onSetSnapshot", information_); +} + +void MemoryInternalsProxy::RequestV8MemoryUpdate() { + renderer_details_->Clear(); +#if !defined(OS_ANDROID) + for (TabContentsIterator iter; !iter.done(); iter.Next()) + renderer_details_->AddWebContents(*iter); +#endif + + // if no contents are shown, update UI. + if (renderer_details_->IsClean()) + CallJavaScriptFunctionOnUIThread("g_main_view.onSetSnapshot", information_); + + renderer_details_->Request(); +} + void MemoryInternalsProxy::OnDetailsAvailable(const ProcessData& browser) { - base::DictionaryValue details; + information_->Clear(); // System information, which is independent from processes. - details.SetInteger("uptime", base::SysInfo::Uptime()); - details.SetString("os", base::SysInfo::OperatingSystemName()); - details.SetString("os_version", base::SysInfo::OperatingSystemVersion()); + information_->SetInteger("uptime", base::SysInfo::Uptime()); + information_->SetString("os", base::SysInfo::OperatingSystemName()); + information_->SetString("os_version", + base::SysInfo::OperatingSystemVersion()); base::ListValue* processes = new ListValue(); base::ListValue* extensions = new ListValue(); - details.Set("processes", processes); - details.Set("extensions", extensions); + information_->Set("processes", processes); + information_->Set("extensions", extensions); for (ProcessMemoryInformationList::const_iterator iter = browser.processes.begin(); iter != browser.processes.end(); ++iter) { - base::DictionaryValue* info = new DictionaryValue(); + base::DictionaryValue* process = new DictionaryValue(); + if (iter->process_type == content::PROCESS_TYPE_RENDERER && + iter->renderer_type == ProcessMemoryInformation::RENDERER_EXTENSION) + extensions->Append(process); + else + processes->Append(process); // Information from MemoryDetails. - info->SetInteger("pid", iter->pid); - info->SetString("type", + process->SetInteger("pid", iter->pid); + process->SetString("type", ProcessMemoryInformation::GetFullTypeNameInEnglish( iter->process_type, iter->renderer_type)); - info->SetInteger("memory_private", iter->working_set.priv); + process->SetInteger("memory_private", iter->working_set.priv); base::ListValue* titles = new ListValue(); - info->Set("titles", titles); + process->Set("titles", titles); for (size_t i = 0; i < iter->titles.size(); ++i) titles->AppendString(iter->titles[i]); - - if (iter->process_type == content::PROCESS_TYPE_RENDERER && - iter->renderer_type == ProcessMemoryInformation::RENDERER_EXTENSION) - extensions->Append(info); - else - processes->Append(info); } - CallJavaScriptFunctionOnUIThread("g_main_view.onSetSnapshot", &details); + RequestV8MemoryUpdate(); } void MemoryInternalsProxy::CallJavaScriptFunctionOnUIThread( diff --git a/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.h b/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.h index f3e4b84..5c5ee78 100644 --- a/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.h +++ b/chrome/browser/ui/webui/memory_internals/memory_internals_proxy.h @@ -9,10 +9,12 @@ #include "base/memory/ref_counted.h" #include "base/strings/string16.h" +#include "base/values.h" #include "chrome/browser/memory_details.h" #include "content/public/browser/browser_thread.h" class MemoryInternalsHandler; +class RendererDetails; namespace base { class ListValue; @@ -21,7 +23,7 @@ class Value; class MemoryInternalsProxy : public base::RefCountedThreadSafe< - MemoryInternalsProxy, content::BrowserThread::DeleteOnUIThread> { + MemoryInternalsProxy, content::BrowserThread::DeleteOnUIThread> { public: MemoryInternalsProxy(); @@ -43,6 +45,12 @@ class MemoryInternalsProxy // Sends a message from IO thread to update UI on UI thread. void UpdateUIOnUIThread(const string16& update); + // Measure memory usage of V8. + void OnV8MemoryUpdate(const base::ProcessId pid, + const size_t v8_allocated, + const size_t v8_used); + void RequestV8MemoryUpdate(); + // Convert memory information into DictionaryValue format. void OnDetailsAvailable(const ProcessData& browser); @@ -51,6 +59,8 @@ class MemoryInternalsProxy base::Value* args); MemoryInternalsHandler* handler_; + base::DictionaryValue* information_; + RendererDetails* renderer_details_; DISALLOW_COPY_AND_ASSIGN(MemoryInternalsProxy); }; |