summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-11 19:24:24 +0000
committerwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-11 19:24:24 +0000
commit01699e2ae35826dc3d16ef6c828c721144443fdd (patch)
treed9f334be31f6dadefef1b0d66cce1f225f315368
parent46d614ab071ce85f57c8099cf8157d104e7fc2fc (diff)
downloadchromium_src-01699e2ae35826dc3d16ef6c828c721144443fdd.zip
chromium_src-01699e2ae35826dc3d16ef6c828c721144443fdd.tar.gz
chromium_src-01699e2ae35826dc3d16ef6c828c721144443fdd.tar.bz2
linux: TCMalloc-based C++ heap profiler.
Requires compiling with linux_use_tcmalloc=1. When enabled by --heap-profiler flag in test_shell exposes chromium.HeapProfiler object to JavaScript. The object has three methods: o start() -- starts profiling o dump() -- dumps data accumulated since start() to file named like chromium-YYYY-MM-DD-TS.heap o stop() -- stops profiling. Output can be analyzed by third_party/tcmalloc/tcmalloc/src/pprof. For example: $ third_party/tcmalloc/tcmalloc/src/pprof \ sconsbuild/Release/test_shell \ chromium-2009-11-06-1234567890.heap See http://code.google.com/p/google-perftools/ for details on how to use pprof. Patch contributed by vitalyr@chromium.org. Original review at http://codereview.chromium.org/377010/show. TBR=vitalyr Review URL: http://codereview.chromium.org/390015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@31688 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/base.gyp3
-rw-r--r--build/common.gypi6
-rw-r--r--webkit/extensions/v8/heap_profiler_extension.cc111
-rw-r--r--webkit/extensions/v8/heap_profiler_extension.h23
-rw-r--r--webkit/tools/test_shell/test_shell_main.cc6
-rw-r--r--webkit/tools/test_shell/test_shell_switches.cc3
-rw-r--r--webkit/tools/test_shell/test_shell_switches.h1
-rw-r--r--webkit/webkit.gyp6
8 files changed, 154 insertions, 5 deletions
diff --git a/base/base.gyp b/base/base.gyp
index 31d9d49..52ffe09 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -376,9 +376,6 @@
],
'conditions': [
[ 'OS == "linux" or OS == "freebsd"', {
- 'variables' : {
- 'linux_use_tcmalloc%': 0,
- },
'sources/': [ ['exclude', '_(mac|win|chromeos)\\.cc$'],
['exclude', '\\.mm?$' ] ],
'conditions': [
diff --git a/build/common.gypi b/build/common.gypi
index a77a13c..1cc8cca 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -176,6 +176,9 @@
# Strip the binary after dumping symbols.
'linux_strip_binary%': 0,
+ # Enable TCMalloc.
+ 'linux_use_tcmalloc%': 0,
+
# Set to select the Title Case versions of strings in GRD files.
'use_titlecase_in_grd_files%': 0,
@@ -709,6 +712,9 @@
}]
],
}],
+ ['linux_use_tcmalloc==1', {
+ 'defines': ['LINUX_USE_TCMALLOC'],
+ }],
],
},
}],
diff --git a/webkit/extensions/v8/heap_profiler_extension.cc b/webkit/extensions/v8/heap_profiler_extension.cc
new file mode 100644
index 0000000..058a5c2
--- /dev/null
+++ b/webkit/extensions/v8/heap_profiler_extension.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2006-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.
+
+#include "webkit/extensions/v8/heap_profiler_extension.h"
+
+#include "base/basictypes.h"
+
+#if defined(LINUX_USE_TCMALLOC)
+#include "third_party/tcmalloc/tcmalloc/src/google/heap-profiler.h"
+#endif
+
+namespace extensions_v8 {
+
+namespace {
+
+const char kHeapProfilerExtensionName[] = "v8/HeapProfiler";
+
+class HeapProfilerWrapper : public v8::Extension {
+ public:
+ HeapProfilerWrapper()
+ : v8::Extension(kHeapProfilerExtensionName,
+ "if (typeof(chromium) == 'undefined') {"
+ " chromium = {};"
+ "}"
+ "(function() {"
+ " native function HeapProfilerStart();"
+ " native function HeapProfilerStop();"
+ " native function HeapProfilerDump();"
+ " chromium.HeapProfiler = {};"
+ " chromium.HeapProfiler.start = function(opt_prefix) {"
+ " var prefix = opt_prefix;"
+ " if (!prefix) {"
+ " var d = new Date();"
+ " prefix = \"chromium-\" + "
+ " (1900 + d.getYear()) + "
+ " \"-\" + d.getMonth() + "
+ " \"-\" + d.getDay() + "
+ " \"-\" + d.getTime();"
+ " }"
+ " HeapProfilerStart(prefix);"
+ " };"
+ " chromium.HeapProfiler.stop = function() {"
+ " HeapProfilerStop();"
+ " };"
+ " chromium.HeapProfiler.dump = function(opt_reason) {"
+ " HeapProfilerDump(opt_reason || \"\");"
+ " };"
+ "})();") {}
+
+ virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+ v8::Handle<v8::String> name) {
+ if (name->Equals(v8::String::New("HeapProfilerStart"))) {
+ return v8::FunctionTemplate::New(HeapProfilerStart);
+ } else if (name->Equals(v8::String::New("HeapProfilerStop"))) {
+ return v8::FunctionTemplate::New(HeapProfilerStop);
+ } else if (name->Equals(v8::String::New("HeapProfilerDump"))) {
+ return v8::FunctionTemplate::New(HeapProfilerDump);
+ }
+ return v8::Handle<v8::FunctionTemplate>();
+ }
+
+#if defined(LINUX_USE_TCMALLOC)
+ static v8::Handle<v8::Value> HeapProfilerStart(const v8::Arguments& args) {
+ if (args.Length() >= 1 && args[0]->IsString()) {
+ v8::Local<v8::String> js_prefix = args[0]->ToString();
+ char prefix[256];
+ js_prefix->WriteAscii(prefix, 0, arraysize(prefix) - 1);
+ ::HeapProfilerStart(prefix);
+ }
+ return v8::Undefined();
+ }
+
+ static v8::Handle<v8::Value> HeapProfilerStop(const v8::Arguments& args) {
+ ::HeapProfilerStop();
+ return v8::Undefined();
+ }
+
+ static v8::Handle<v8::Value> HeapProfilerDump(const v8::Arguments& args) {
+ if (args.Length() >= 1 && args[0]->IsString()) {
+ v8::Local<v8::String> js_reason = args[0]->ToString();
+ char reason[256];
+ js_reason->WriteAscii(reason, 0, arraysize(reason) - 1);
+ ::HeapProfilerDump(reason);
+ }
+ return v8::Undefined();
+ }
+
+#else
+
+ static v8::Handle<v8::Value> HeapProfilerStart(const v8::Arguments& args) {
+ return v8::Undefined();
+ }
+
+ static v8::Handle<v8::Value> HeapProfilerStop(const v8::Arguments& args) {
+ return v8::Undefined();
+ }
+
+ static v8::Handle<v8::Value> HeapProfilerDump(const v8::Arguments& args) {
+ return v8::Undefined();
+ }
+#endif
+};
+
+} // namespace
+
+v8::Extension* HeapProfilerExtension::Get() {
+ return new HeapProfilerWrapper;
+}
+
+} // namespace extensions_v8
diff --git a/webkit/extensions/v8/heap_profiler_extension.h b/webkit/extensions/v8/heap_profiler_extension.h
new file mode 100644
index 0000000..8bdbf90
--- /dev/null
+++ b/webkit/extensions/v8/heap_profiler_extension.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2006-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.
+
+// HeapProfilerExtension is a V8 extension to expose a JS function for
+// dumping native heap profiles. This should only be used for
+// debugging.
+
+#ifndef WEBKIT_EXTENSIONS_V8_HEAP_PROFILER_EXTENSION_H_
+#define WEBKIT_EXTENSIONS_V8_HEAP_PROFILER_EXTENSION_H_
+
+#include "v8/include/v8.h"
+
+namespace extensions_v8 {
+
+class HeapProfilerExtension {
+ public:
+ static v8::Extension* Get();
+};
+
+} // namespace extensions_v8
+
+#endif // WEBKIT_EXTENSIONS_V8_HEAP_PROFILER_EXTENSION_H_
diff --git a/webkit/tools/test_shell/test_shell_main.cc b/webkit/tools/test_shell/test_shell_main.cc
index b069b2f..ea2d625 100644
--- a/webkit/tools/test_shell/test_shell_main.cc
+++ b/webkit/tools/test_shell/test_shell_main.cc
@@ -29,6 +29,7 @@
#include "webkit/glue/webkit_glue.h"
#include "webkit/glue/window_open_disposition.h"
#include "webkit/extensions/v8/gc_extension.h"
+#include "webkit/extensions/v8/heap_profiler_extension.h"
#include "webkit/extensions/v8/playback_extension.h"
#include "webkit/extensions/v8/profiler_extension.h"
#include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
@@ -225,6 +226,11 @@ int main(int argc, char* argv[]) {
extensions_v8::ProfilerExtension::Get());
}
+ if (parsed_command_line.HasSwitch(test_shell::kHeapProfiler)) {
+ WebScriptController::registerExtension(
+ extensions_v8::HeapProfilerExtension::Get());
+ }
+
// Load and initialize the stats table. Attempt to construct a somewhat
// unique name to isolate separate instances from each other.
StatsTable *table = new StatsTable(
diff --git a/webkit/tools/test_shell/test_shell_switches.cc b/webkit/tools/test_shell/test_shell_switches.cc
index 1142ee1..d0bf04c 100644
--- a/webkit/tools/test_shell/test_shell_switches.cc
+++ b/webkit/tools/test_shell/test_shell_switches.cc
@@ -82,4 +82,7 @@ extern const char kGDB[] = "gdb";
// Make functions of the Profiler class available in javascript
extern const char kProfiler[] = "profiler";
+// Make functions of the HeapProfiler class available in javascript
+extern const char kHeapProfiler[] = "heap-profiler";
+
} // namespace test_shell
diff --git a/webkit/tools/test_shell/test_shell_switches.h b/webkit/tools/test_shell/test_shell_switches.h
index d580695..0330e0a 100644
--- a/webkit/tools/test_shell/test_shell_switches.h
+++ b/webkit/tools/test_shell/test_shell_switches.h
@@ -33,6 +33,7 @@ extern const char kAllowScriptsToCloseWindows[];
extern const char kCheckLayoutTestSystemDeps[];
extern const char kGDB[];
extern const char kProfiler[];
+extern const char kHeapProfiler[];
} // namespace test_shell
diff --git a/webkit/webkit.gyp b/webkit/webkit.gyp
index 9bf19c7..b6212a6 100644
--- a/webkit/webkit.gyp
+++ b/webkit/webkit.gyp
@@ -379,18 +379,20 @@
# These files used to be built in the webcore target, but moved here
# since part of glue.
+ 'extensions/v8/benchmarking_extension.cc',
+ 'extensions/v8/benchmarking_extension.h',
'extensions/v8/gc_extension.cc',
'extensions/v8/gc_extension.h',
'extensions/v8/gears_extension.cc',
'extensions/v8/gears_extension.h',
+ 'extensions/v8/heap_profiler_extension.cc',
+ 'extensions/v8/heap_profiler_extension.h',
'extensions/v8/interval_extension.cc',
'extensions/v8/interval_extension.h',
'extensions/v8/playback_extension.cc',
'extensions/v8/playback_extension.h',
'extensions/v8/profiler_extension.cc',
'extensions/v8/profiler_extension.h',
- 'extensions/v8/benchmarking_extension.cc',
- 'extensions/v8/benchmarking_extension.h',
],
# When glue is a dependency, it needs to be a hard dependency.