diff options
author | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-11 19:24:24 +0000 |
---|---|---|
committer | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-11 19:24:24 +0000 |
commit | 01699e2ae35826dc3d16ef6c828c721144443fdd (patch) | |
tree | d9f334be31f6dadefef1b0d66cce1f225f315368 | |
parent | 46d614ab071ce85f57c8099cf8157d104e7fc2fc (diff) | |
download | chromium_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.gyp | 3 | ||||
-rw-r--r-- | build/common.gypi | 6 | ||||
-rw-r--r-- | webkit/extensions/v8/heap_profiler_extension.cc | 111 | ||||
-rw-r--r-- | webkit/extensions/v8/heap_profiler_extension.h | 23 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_main.cc | 6 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_switches.cc | 3 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_switches.h | 1 | ||||
-rw-r--r-- | webkit/webkit.gyp | 6 |
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. |