diff options
author | jamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-11 01:51:32 +0000 |
---|---|---|
committer | jamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-11 01:51:32 +0000 |
commit | 38b48a844731cd10d69d8e99d476e3dac9e81980 (patch) | |
tree | b73cc4ca2cae009276db4305eac119d080f0381f | |
parent | 5ecc992a4bf8546b21db89901f2d87e8b4ae1a94 (diff) | |
download | chromium_src-38b48a844731cd10d69d8e99d476e3dac9e81980.zip chromium_src-38b48a844731cd10d69d8e99d476e3dac9e81980.tar.gz chromium_src-38b48a844731cd10d69d8e99d476e3dac9e81980.tar.bz2 |
Adds a 'V8' column to task manager to track amount of memory in JavaScript heap
BUG=27226
TEST=open task manager, enable column, compare with V8 heap profiler
Review URL: http://codereview.chromium.org/377037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@31641 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/generated_resources.grd | 5 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.cc | 22 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.h | 5 | ||||
-rw-r--r-- | chrome/browser/task_manager.cc | 24 | ||||
-rw-r--r-- | chrome/browser/task_manager.h | 13 | ||||
-rw-r--r-- | chrome/browser/task_manager_resource_providers.cc | 24 | ||||
-rw-r--r-- | chrome/browser/task_manager_resource_providers.h | 16 | ||||
-rw-r--r-- | chrome/browser/views/task_manager_view.cc | 11 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 10 | ||||
-rw-r--r-- | chrome/renderer/render_thread.cc | 10 | ||||
-rw-r--r-- | chrome/renderer/render_thread.h | 1 |
11 files changed, 134 insertions, 7 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 1729d19..dae19c5 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -2508,11 +2508,14 @@ each locale. --> <message name="IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN" desc="Amount of memory used by SQLite."> SQLite memory </message> + <message name="IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN" desc="Task manager JavaScript memory allocated column. Shows the amount of memory used by JavaScript within a process"> + JavaScript memory + </message> <message name="IDS_TASK_MANAGER_MEM_CELL_TEXT" desc="The value displayed in the memory usage cells."> <ph name="NUM_KILOBYTES">$1<ex>5,000</ex></ph>K </message> <message name="IDS_TASK_MANAGER_CACHE_SIZE_CELL_TEXT" desc="The value displayed in the cache size cells."> - <ph name="NUM_KILOBYTES">$1<ex>5,000</ex></ph>K (<ph name="NUM_KILOBYTES">$2<ex>5,000</ex></ph>K live) + <ph name="NUM_KILOBYTES">$1<ex>5,000</ex></ph>K (<ph name="NUM_KILOBYTES_LIVE">$2<ex>5,000</ex></ph>K live) </message> <message name="IDS_TASK_MANAGER_NA_CELL_TEXT" desc="The value displayed for network / webcache usage when the information is not available (Not Applicable)."> N/A diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 41ddd3d..a7d53c0 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -369,6 +369,7 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) { OnAllocatePDFTransport) #endif IPC_MESSAGE_HANDLER(ViewHostMsg_ResourceTypeStats, OnResourceTypeStats) + IPC_MESSAGE_HANDLER(ViewHostMsg_V8HeapStats, OnV8HeapStats) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ResolveProxy, OnResolveProxy) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetDefaultPrintSettings, OnGetDefaultPrintSettings) @@ -827,6 +828,27 @@ void ResourceMessageFilter::OnResourceTypeStatsOnUIThread( renderer_id, stats); } + +void ResourceMessageFilter::OnV8HeapStats(int v8_memory_allocated, + int v8_memory_used) { + ChromeThread::PostTask( + ChromeThread::UI, FROM_HERE, + NewRunnableFunction(&ResourceMessageFilter::OnV8HeapStatsOnUIThread, + v8_memory_allocated, + v8_memory_used, + base::GetProcId(handle()))); +} + +// static +void ResourceMessageFilter::OnV8HeapStatsOnUIThread( + int v8_memory_allocated, int v8_memory_used, base::ProcessId renderer_id) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); + TaskManager::GetInstance()->model()->NotifyV8HeapStats( + renderer_id, + static_cast<size_t>(v8_memory_allocated), + static_cast<size_t>(v8_memory_used)); +} + void ResourceMessageFilter::OnResolveProxy(const GURL& url, IPC::Message* reply_msg) { resolve_proxy_msg_helper_.Start(url, reply_msg); diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index 84a5a33..250b737 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -244,6 +244,11 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, static void OnResourceTypeStatsOnUIThread(WebKit::WebCache::ResourceTypeStats, base::ProcessId renderer_id); + void OnV8HeapStats(int v8_memory_allocated, int v8_memory_used); + static void OnV8HeapStatsOnUIThread(int v8_memory_allocated, + int v8_memory_used, + base::ProcessId renderer_id); + void OnResolveProxy(const GURL& url, IPC::Message* reply_msg); // ResolveProxyMsgHelper::Delegate implementation: diff --git a/chrome/browser/task_manager.cc b/chrome/browser/task_manager.cc index 43e2657..090f626 100644 --- a/chrome/browser/task_manager.cc +++ b/chrome/browser/task_manager.cc @@ -196,6 +196,19 @@ std::wstring TaskManagerModel::GetResourceSqliteMemoryUsed(int index) const { return GetMemCellText(resources_[index]->SqliteMemoryUsedBytes() / 1024); } +std::wstring TaskManagerModel::GetResourceV8MemoryAllocatedSize( + int index) const { + if (!resources_[index]->ReportsV8MemoryStats()) + return l10n_util::GetString(IDS_TASK_MANAGER_NA_CELL_TEXT); + return l10n_util::GetStringF(IDS_TASK_MANAGER_CACHE_SIZE_CELL_TEXT, + FormatBytes(resources_[index]->GetV8MemoryAllocated(), + DATA_UNITS_KILOBYTE, + false), + FormatBytes(resources_[index]->GetV8MemoryUsed(), + DATA_UNITS_KILOBYTE, + false)); +} + bool TaskManagerModel::IsResourceFirstInGroup(int index) const { DCHECK(index < ResourceCount()); TaskManager::Resource* resource = resources_[index]; @@ -621,6 +634,17 @@ void TaskManagerModel::NotifyResourceTypeStats( } } +void TaskManagerModel::NotifyV8HeapStats(base::ProcessId renderer_id, + size_t v8_memory_allocated, + size_t v8_memory_used) { + for (ResourceList::iterator it = resources_.begin(); + it != resources_.end(); ++it) { + if (base::GetProcId((*it)->GetProcess()) == renderer_id) { + (*it)->NotifyV8HeapStats(v8_memory_allocated, v8_memory_used); + } + } +} + void TaskManagerModel::Refresh() { DCHECK_NE(IDLE, update_state_); diff --git a/chrome/browser/task_manager.h b/chrome/browser/task_manager.h index 9fa19f6..2c76a7d 100644 --- a/chrome/browser/task_manager.h +++ b/chrome/browser/task_manager.h @@ -59,6 +59,10 @@ class TaskManager { // if not applicable. virtual const Extension* GetExtension() const { return NULL; } + virtual bool ReportsV8MemoryStats() const { return false; } + virtual size_t GetV8MemoryAllocated() const { return 0; } + virtual size_t GetV8MemoryUsed() const { return 0; } + // A helper function for ActivateFocusedTab. Returns NULL by default // because not all resources have an associated tab. virtual TabContents* GetTabContents() const { return NULL; } @@ -80,6 +84,8 @@ class TaskManager { virtual void NotifyResourceTypeStats( const WebKit::WebCache::ResourceTypeStats& stats) {} + virtual void NotifyV8HeapStats(size_t v8_memory_allocated, + size_t v8_memory_used) {} }; // ResourceProviders are responsible for adding/removing resources to the task @@ -202,6 +208,7 @@ class TaskManagerModel : public URLRequestJobTracker::JobObserver, std::wstring GetResourceWebCoreCSSCacheSize(int index) const; std::wstring GetResourceSqliteMemoryUsed(int index) const; std::wstring GetResourceGoatsTeleported(int index) const; + std::wstring GetResourceV8MemoryAllocatedSize(int index) const; // Returns true if the resource is first in its group (resources // rendered by the same process are groupped together). @@ -246,9 +253,13 @@ class TaskManagerModel : public URLRequestJobTracker::JobObserver, void Clear(); // Removes all items. void NotifyResourceTypeStats( - base::ProcessId renderer_handle, + base::ProcessId renderer_id, const WebKit::WebCache::ResourceTypeStats& stats); + void NotifyV8HeapStats(base::ProcessId renderer_id, + size_t v8_memory_allocated, + size_t v8_memory_used); + private: friend class base::RefCountedThreadSafe<TaskManagerModel>; FRIEND_TEST(TaskManagerTest, RefreshCalled); diff --git a/chrome/browser/task_manager_resource_providers.cc b/chrome/browser/task_manager_resource_providers.cc index 5aba2db..20100c0 100644 --- a/chrome/browser/task_manager_resource_providers.cc +++ b/chrome/browser/task_manager_resource_providers.cc @@ -47,7 +47,10 @@ TaskManagerTabContentsResource::TaskManagerTabContentsResource( TabContents* tab_contents) : tab_contents_(tab_contents), - pending_stats_update_(false) { + pending_stats_update_(false), + v8_memory_allocated_(0), + v8_memory_used_(0), + pending_v8_memory_allocated_update_(false) { // We cache the process as when the TabContents is closed the process // becomes NULL and the TaskManager still needs it. process_ = tab_contents_->process()->process().handle(); @@ -91,6 +94,10 @@ void TaskManagerTabContentsResource::Refresh() { tab_contents_->render_view_host()->Send(new ViewMsg_GetCacheResourceStats); pending_stats_update_ = true; } + if (!pending_v8_memory_allocated_update_) { + tab_contents_->render_view_host()->Send(new ViewMsg_GetV8HeapStats); + pending_v8_memory_allocated_update_ = true; + } } WebKit::WebCache::ResourceTypeStats @@ -98,12 +105,27 @@ WebKit::WebCache::ResourceTypeStats return stats_; } +size_t TaskManagerTabContentsResource::GetV8MemoryAllocated() const { + return v8_memory_allocated_; +} + +size_t TaskManagerTabContentsResource::GetV8MemoryUsed() const { + return v8_memory_used_; +} + void TaskManagerTabContentsResource::NotifyResourceTypeStats( const WebKit::WebCache::ResourceTypeStats& stats) { stats_ = stats; pending_stats_update_ = false; } +void TaskManagerTabContentsResource::NotifyV8HeapStats( + size_t v8_memory_allocated, size_t v8_memory_used) { + v8_memory_allocated_ = v8_memory_allocated; + v8_memory_used_ = v8_memory_used; + pending_v8_memory_allocated_update_ = false; +} + SkBitmap TaskManagerTabContentsResource::GetIcon() const { return tab_contents_->GetFavIcon(); } diff --git a/chrome/browser/task_manager_resource_providers.h b/chrome/browser/task_manager_resource_providers.h index ae3bf100..b374a65 100644 --- a/chrome/browser/task_manager_resource_providers.h +++ b/chrome/browser/task_manager_resource_providers.h @@ -35,6 +35,10 @@ class TaskManagerTabContentsResource : public TaskManager::Resource { virtual bool ReportsCacheStats() const { return true; } virtual WebKit::WebCache::ResourceTypeStats GetWebCoreCacheStats() const; + virtual bool ReportsV8MemoryStats() const { return true; } + virtual size_t GetV8MemoryAllocated() const; + virtual size_t GetV8MemoryUsed() const; + // TabContents always provide the network usage. bool SupportNetworkUsage() const { return true; } void SetSupportNetworkUsage() { } @@ -44,18 +48,24 @@ class TaskManagerTabContentsResource : public TaskManager::Resource { virtual void NotifyResourceTypeStats( const WebKit::WebCache::ResourceTypeStats& stats); + virtual void NotifyV8HeapStats(size_t v8_memory_allocated, + size_t v8_memory_used); + private: TabContents* tab_contents_; base::ProcessHandle process_; int pid_; // The stats_ field holds information about resource usage in the renderer - // process and so it is updated asynchronously. A query to any of the - // GetWebCore*CacheSize() functions will send an IPC to the renderer asking - // for an update unless a query is already outstanding. + // process and so it is updated asynchronously by the Refresh() call. WebKit::WebCache::ResourceTypeStats stats_; // This flag is true if we are waiting for the renderer to report its stats. bool pending_stats_update_; + // We do a similar dance to gather the V8 memory usage in a process. + size_t v8_memory_allocated_; + size_t v8_memory_used_; + bool pending_v8_memory_allocated_update_; + DISALLOW_COPY_AND_ASSIGN(TaskManagerTabContentsResource); }; diff --git a/chrome/browser/views/task_manager_view.cc b/chrome/browser/views/task_manager_view.cc index 468562e..bcfb422 100644 --- a/chrome/browser/views/task_manager_view.cc +++ b/chrome/browser/views/task_manager_view.cc @@ -133,6 +133,11 @@ std::wstring TaskManagerTableModel::GetText(int row, int col_id) { return std::wstring(); return model_->GetResourceSqliteMemoryUsed(row); + case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN: + if (!model_->IsResourceFirstInGroup(row)) + return std::wstring(); + return model_->GetResourceV8MemoryAllocatedSize(row); + default: return model_->GetResourceStatsValue(row, col_id); } @@ -330,6 +335,10 @@ void TaskManagerView::Init() { columns_.push_back(TableColumn(IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN, TableColumn::RIGHT, -1, 0)); columns_.back().sortable = true; + columns_.push_back( + TableColumn(IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN, + TableColumn::RIGHT, -1, 0)); + columns_.back().sortable = true; tab_table_ = new views::GroupTableView(table_model_.get(), columns_, views::ICON_AND_TEXT, false, true, @@ -347,6 +356,8 @@ void TaskManagerView::Init() { false); tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN, false); + tab_table_->SetColumnVisibility( + IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN, false); tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN, false); diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 373a914..2ad32ab 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. + // Copyright (c) 2009 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. @@ -550,6 +550,9 @@ IPC_BEGIN_MESSAGES(View) IPC_MESSAGE_CONTROL0(ViewMsg_GetRendererTcmalloc) #endif + // Asks the renderer to send back V8 heap stats. + IPC_MESSAGE_CONTROL0(ViewMsg_GetV8HeapStats) + // Notifies the renderer about ui theme changes IPC_MESSAGE_ROUTED0(ViewMsg_ThemeChanged) @@ -1449,6 +1452,11 @@ IPC_BEGIN_MESSAGES(ViewHost) std::string /* tcmalloc debug output */) #endif + // Sends back stats about the V8 heap. + IPC_MESSAGE_CONTROL2(ViewHostMsg_V8HeapStats, + int /* size of heap (allocated from the OS) */, + int /* bytes in use */) + // Request for a DNS prefetch of the names in the array. // NameList is typedef'ed std::vector<std::string> IPC_MESSAGE_CONTROL1(ViewHostMsg_DnsPrefetch, diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index 8f3bac5..323d0f0 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -4,6 +4,8 @@ #include "chrome/renderer/render_thread.h" +#include <v8.h> + #include <algorithm> #include <map> #include <vector> @@ -310,6 +312,7 @@ void RenderThread::OnControlMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(ViewMsg_GetRendererTcmalloc, OnGetRendererTcmalloc) #endif + IPC_MESSAGE_HANDLER(ViewMsg_GetV8HeapStats, OnGetV8HeapStats) IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats, OnGetCacheResourceStats) IPC_MESSAGE_HANDLER(ViewMsg_UserScripts_UpdatedScripts, @@ -416,6 +419,13 @@ void RenderThread::OnGetRendererTcmalloc() { } #endif +void RenderThread::OnGetV8HeapStats() { + v8::HeapStatistics heap_stats; + v8::V8::GetHeapStatistics(&heap_stats); + Send(new ViewHostMsg_V8HeapStats(heap_stats.total_heap_size(), + heap_stats.used_heap_size())); +} + void RenderThread::InformHostOfCacheStats() { EnsureWebKitInitialized(); WebCache::UsageStats stats; diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h index dece3ee..d7f15a1 100644 --- a/chrome/renderer/render_thread.h +++ b/chrome/renderer/render_thread.h @@ -192,6 +192,7 @@ class RenderThread : public RenderThreadBase, // Send tcmalloc info to browser. void OnGetRendererTcmalloc(); + void OnGetV8HeapStats(); void OnExtensionMessageInvoke(const std::string& function_name, const ListValue& args); |