diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-15 23:34:22 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-15 23:34:22 +0000 |
commit | 0500118146171bc4a57ba51cec620b51f139dab8 (patch) | |
tree | 015430d44f2e8cd90d4d4bbf0e4f4171d3179fc3 /third_party | |
parent | e7f27c9f51fd960b72eda1afbfa36aee2d5a478f (diff) | |
download | chromium_src-0500118146171bc4a57ba51cec620b51f139dab8.zip chromium_src-0500118146171bc4a57ba51cec620b51f139dab8.tar.gz chromium_src-0500118146171bc4a57ba51cec620b51f139dab8.tar.bz2 |
Issue 172109: Enable scavenging in RenderThread::IdleHandler.
Landing of Anton Muhin's patch (antonm@google.com)
(Reland. First landed in r26264, reverted in r26276. This reland hopefully
doesn't build tcmalloc on Linux.)
Review URL: http://codereview.chromium.org/206017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26298 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party')
-rw-r--r-- | third_party/tcmalloc/config_linux.h | 2 | ||||
-rw-r--r-- | third_party/tcmalloc/config_win.h | 2 | ||||
-rw-r--r-- | third_party/tcmalloc/google/malloc_extension.h | 239 | ||||
-rw-r--r-- | third_party/tcmalloc/malloc_extension.cc | 326 | ||||
-rw-r--r-- | third_party/tcmalloc/tcmalloc.cc | 5 | ||||
-rw-r--r-- | third_party/tcmalloc/tcmalloc.gyp | 15 |
6 files changed, 586 insertions, 3 deletions
diff --git a/third_party/tcmalloc/config_linux.h b/third_party/tcmalloc/config_linux.h index af12784..e813dc5 100644 --- a/third_party/tcmalloc/config_linux.h +++ b/third_party/tcmalloc/config_linux.h @@ -35,7 +35,7 @@ (on OSes which have ability) which could be performed offline (either by background thread or in idle time.) */ -#define DEFER_DECOMMIT 0 +#define DEFER_DECOMMIT 1 /* Define to 1 if you have the <dlfcn.h> header file. */ #define HAVE_DLFCN_H 1 diff --git a/third_party/tcmalloc/config_win.h b/third_party/tcmalloc/config_win.h index 51c73c5..9bca17b 100644 --- a/third_party/tcmalloc/config_win.h +++ b/third_party/tcmalloc/config_win.h @@ -65,7 +65,7 @@ (on OSes which have ability) which could be performed offline (either by background thread or in idle time.) */ -#define DEFER_DECOMMIT 0 +#define DEFER_DECOMMIT 1 /* Define to 1 if you have the <dlfcn.h> header file. */ #undef HAVE_DLFCN_H diff --git a/third_party/tcmalloc/google/malloc_extension.h b/third_party/tcmalloc/google/malloc_extension.h new file mode 100644 index 0000000..8264787 --- /dev/null +++ b/third_party/tcmalloc/google/malloc_extension.h @@ -0,0 +1,239 @@ +// Copyright (c) 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// --- +// Author: Sanjay Ghemawat <opensource@google.com> +// +// Extra extensions exported by some malloc implementations. These +// extensions are accessed through a virtual base class so an +// application can link against a malloc that does not implement these +// extensions, and it will get default versions that do nothing. +// +// NOTE FOR C USERS: If you wish to use this functionality from within +// a C program, see malloc_extension_c.h. + +#ifndef BASE_MALLOC_EXTENSION_H_ +#define BASE_MALLOC_EXTENSION_H_ + +#include <stddef.h> +#include <string> + +// Annoying stuff for windows -- makes sure clients can import these functions +#ifndef PERFTOOLS_DLL_DECL +# ifdef _WIN32 +# define PERFTOOLS_DLL_DECL __declspec(dllimport) +# else +# define PERFTOOLS_DLL_DECL +# endif +#endif + +static const int kMallocHistogramSize = 64; + +// One day, we could support other types of writers (perhaps for C?) +typedef std::string MallocExtensionWriter; + +// The default implementations of the following routines do nothing. +// All implementations should be thread-safe; the current one +// (TCMallocImplementation) is. +class PERFTOOLS_DLL_DECL MallocExtension { + public: + virtual ~MallocExtension(); + + // Call this very early in the program execution -- say, in a global + // constructor -- to set up parameters and state needed by all + // instrumented malloc implemenatations. One example: this routine + // sets environemnt variables to tell STL to use libc's malloc() + // instead of doing its own memory management. This is safe to call + // multiple times, as long as each time is before threads start up. + static void Initialize(); + + // See "verify_memory.h" to see what these routines do + virtual bool VerifyAllMemory(); + virtual bool VerifyNewMemory(void* p); + virtual bool VerifyArrayNewMemory(void* p); + virtual bool VerifyMallocMemory(void* p); + virtual bool MallocMemoryStats(int* blocks, size_t* total, + int histogram[kMallocHistogramSize]); + + // Get a human readable description of the current state of the malloc + // data structures. The state is stored as a null-terminated string + // in a prefix of "buffer[0,buffer_length-1]". + // REQUIRES: buffer_length > 0. + virtual void GetStats(char* buffer, int buffer_length); + + // Outputs to "writer" a sample of live objects and the stack traces + // that allocated these objects. The format of the returned output + // is equivalent to the output of the heap profiler and can + // therefore be passed to "pprof". + virtual void GetHeapSample(MallocExtensionWriter* writer); + + // Outputs to "writer" the stack traces that caused growth in the + // address space size. The format of the returned output is + // equivalent to the output of the heap profiler and can therefore + // be passed to "pprof". + virtual void GetHeapGrowthStacks(MallocExtensionWriter* writer); + + // ------------------------------------------------------------------- + // Control operations for getting and setting malloc implementation + // specific parameters. Some currently useful properties: + // + // generic + // ------- + // "generic.current_allocated_bytes" + // Number of bytes currently allocated by application + // This property is not writable. + // + // "generic.heap_size" + // Number of bytes in the heap == + // current_allocated_bytes + + // fragmentation + + // freed memory regions + // This property is not writable. + // + // tcmalloc + // -------- + // "tcmalloc.max_total_thread_cache_bytes" + // Upper limit on total number of bytes stored across all + // per-thread caches. Default: 16MB. + // + // "tcmalloc.current_total_thread_cache_bytes" + // Number of bytes used across all thread caches. + // This property is not writable. + // + // "tcmalloc.slack_bytes" + // Number of bytes allocated from system, but not currently + // in use by malloced objects. I.e., bytes available for + // allocation without needing more bytes from system. + // This property is not writable. + // + // TODO: Add more properties as necessary + // ------------------------------------------------------------------- + + // Get the named "property"'s value. Returns true if the property + // is known. Returns false if the property is not a valid property + // name for the current malloc implementation. + // REQUIRES: property != NULL; value != NULL + virtual bool GetNumericProperty(const char* property, size_t* value); + + // Set the named "property"'s value. Returns true if the property + // is known and writable. Returns false if the property is not a + // valid property name for the current malloc implementation, or + // is not writable. + // REQUIRES: property != NULL + virtual bool SetNumericProperty(const char* property, size_t value); + + // Mark the current thread as "idle". This routine may optionally + // be called by threads as a hint to the malloc implementation that + // any thread-specific resources should be released. Note: this may + // be an expensive routine, so it should not be called too often. + // + // Also, if the code that calls this routine will go to sleep for + // a while, it should take care to not allocate anything between + // the call to this routine and the beginning of the sleep. + // + // Most malloc implementations ignore this routine. + virtual void MarkThreadIdle(); + + // Scavenge at least some resources and free them back to OS. + // This method doesn't promise to do anything useful (it might be + // implemented as noop), but it's a good idea to invoke it when + // application is idle. + virtual void Scavenge(); + + // Try to free memory back to the operating system for reuse. Only + // use this extension if the application has recently freed a lot of + // memory, and does not anticipate using it again for a long time -- + // to get this memory back may require faulting pages back in by the + // OS, and that may be slow. (Currently only implemented in + // tcmalloc.) + virtual void ReleaseFreeMemory(); + + // Sets the rate at which we release unused memory to the system. + // Zero means we never release memory back to the system. Increase + // this flag to return memory faster; decrease it to return memory + // slower. Reasonable rates are in the range [0,10]. (Currently + // only implemented in tcmalloc). + virtual void SetMemoryReleaseRate(double rate); + + // Gets the release rate. Returns a value < 0 if unknown. + virtual double GetMemoryReleaseRate(); + + // Returns the estimated number of bytes that will be allocated for + // a request of "size" bytes. This is an estimate: an allocation of + // SIZE bytes may reserve more bytes, but will never reserve less. + // (Currently only implemented in tcmalloc, other implementations + // always return SIZE.) + virtual size_t GetEstimatedAllocatedSize(size_t size); + + // Returns the actual number of bytes reserved by tcmalloc for the + // pointer p. This number may be equal to or greater than + // the number of bytes requested when p was allocated. + // p must have been allocated by this malloc implementation, + // must not be an interior pointer -- that is, must be exactly + // the pointer returned to by malloc() et al., not some offset + // from that -- and should not have been freed yet. p may be NULL. + // (Currently only implemented in tcmalloc; other implementations + // will return 0.) + virtual size_t GetAllocatedSize(void* p); + + // The current malloc implementation. Always non-NULL. + static MallocExtension* instance(); + + // Change the malloc implementation. Typically called by the + // malloc implementation during initialization. + static void Register(MallocExtension* implementation); + + protected: + // Get a list of stack traces of sampled allocation points. Returns + // a pointer to a "new[]-ed" result array, and stores the sample + // period in "sample_period". + // + // The state is stored as a sequence of adjacent entries + // in the returned array. Each entry has the following form: + // uintptr_t count; // Number of objects with following trace + // uintptr_t size; // Total size of objects with following trace + // uintptr_t depth; // Number of PC values in stack trace + // void* stack[depth]; // PC values that form the stack trace + // + // The list of entries is terminated by a "count" of 0. + // + // It is the responsibility of the caller to "delete[]" the returned array. + // + // May return NULL to indicate no results. + // + // This is an internal extension. Callers should use the more + // convenient "GetHeapSample(string*)" method defined above. + virtual void** ReadStackTraces(int* sample_period); + + // Like ReadStackTraces(), but returns stack traces that caused growth + // in the address space size. + virtual void** ReadHeapGrowthStackTraces(); +}; + +#endif // BASE_MALLOC_EXTENSION_H_ diff --git a/third_party/tcmalloc/malloc_extension.cc b/third_party/tcmalloc/malloc_extension.cc new file mode 100644 index 0000000..c681c4e --- /dev/null +++ b/third_party/tcmalloc/malloc_extension.cc @@ -0,0 +1,326 @@ +// Copyright (c) 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// --- +// Author: Sanjay Ghemawat <opensource@google.com> + +#include <config.h> +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <stdio.h> +#if defined HAVE_STDINT_H +#include <stdint.h> +#elif defined HAVE_INTTYPES_H +#include <inttypes.h> +#else +#include <sys/types.h> +#endif +#include <string> +#include "base/dynamic_annotations.h" +#include "base/sysinfo.h" // for FillProcSelfMaps +#include "google/malloc_extension.h" +#include "maybe_threads.h" + +using STL_NAMESPACE::string; + +static void DumpAddressMap(string* result) { + *result += "\nMAPPED_LIBRARIES:\n"; + // We keep doubling until we get a fit + const size_t old_resultlen = result->size(); + for (int amap_size = 10240; amap_size < 10000000; amap_size *= 2) { + result->resize(old_resultlen + amap_size); + const int bytes_written = + tcmalloc::FillProcSelfMaps(&((*result)[old_resultlen]), amap_size); + if (bytes_written < amap_size - 1) { // we fit! + (*result)[old_resultlen + bytes_written] = '\0'; + result->resize(old_resultlen + bytes_written); + return; + } + } + result->reserve(old_resultlen); // just don't print anything +} + +// Note: this routine is meant to be called before threads are spawned. +void MallocExtension::Initialize() { + static bool initialize_called = false; + + if (initialize_called) return; + initialize_called = true; + +#ifdef __GLIBC__ + // GNU libc++ versions 3.3 and 3.4 obey the environment variables + // GLIBCPP_FORCE_NEW and GLIBCXX_FORCE_NEW respectively. Setting + // one of these variables forces the STL default allocator to call + // new() or delete() for each allocation or deletion. Otherwise + // the STL allocator tries to avoid the high cost of doing + // allocations by pooling memory internally. However, tcmalloc + // does allocations really fast, especially for the types of small + // items one sees in STL, so it's better off just using us. + // TODO: control whether we do this via an environment variable? + setenv("GLIBCPP_FORCE_NEW", "1", false /* no overwrite*/); + setenv("GLIBCXX_FORCE_NEW", "1", false /* no overwrite*/); + + // Now we need to make the setenv 'stick', which it may not do since + // the env is flakey before main() is called. But luckily stl only + // looks at this env var the first time it tries to do an alloc, and + // caches what it finds. So we just cause an stl alloc here. + string dummy("I need to be allocated"); + dummy += "!"; // so the definition of dummy isn't optimized out +#endif /* __GLIBC__ */ +} + +// Default implementation -- does nothing +MallocExtension::~MallocExtension() { } +bool MallocExtension::VerifyAllMemory() { return true; } +bool MallocExtension::VerifyNewMemory(void* p) { return true; } +bool MallocExtension::VerifyArrayNewMemory(void* p) { return true; } +bool MallocExtension::VerifyMallocMemory(void* p) { return true; } + +bool MallocExtension::GetNumericProperty(const char* property, size_t* value) { + return false; +} + +bool MallocExtension::SetNumericProperty(const char* property, size_t value) { + return false; +} + +void MallocExtension::GetStats(char* buffer, int length) { + assert(length > 0); + buffer[0] = '\0'; +} + +bool MallocExtension::MallocMemoryStats(int* blocks, size_t* total, + int histogram[kMallocHistogramSize]) { + *blocks = 0; + *total = 0; + memset(histogram, 0, sizeof(histogram)); + return true; +} + +void** MallocExtension::ReadStackTraces(int* sample_period) { + return NULL; +} + +void** MallocExtension::ReadHeapGrowthStackTraces() { + return NULL; +} + +void MallocExtension::MarkThreadIdle() { + // Default implementation does nothing +} + +void MallocExtension::ReleaseFreeMemory() { + // Default implementation does nothing +} + +void MallocExtension::Scavenge() { + // Default implementation does nothing +} + +void MallocExtension::SetMemoryReleaseRate(double rate) { + // Default implementation does nothing +} + +double MallocExtension::GetMemoryReleaseRate() { + return -1.0; +} + +size_t MallocExtension::GetEstimatedAllocatedSize(size_t size) { + return size; +} + +size_t MallocExtension::GetAllocatedSize(void* p) { + return 0; +} + +// The current malloc extension object. We also keep a pointer to +// the default implementation so that the heap-leak checker does not +// complain about a memory leak. + +static pthread_once_t module_init = PTHREAD_ONCE_INIT; +static MallocExtension* default_instance = NULL; +static MallocExtension* current_instance = NULL; + +static void InitModule() { + default_instance = new MallocExtension; + current_instance = default_instance; +} + +MallocExtension* MallocExtension::instance() { + perftools_pthread_once(&module_init, InitModule); + return current_instance; +} + +void MallocExtension::Register(MallocExtension* implementation) { + perftools_pthread_once(&module_init, InitModule); + // When running under valgrind, our custom malloc is replaced with + // valgrind's one and malloc extensions will not work. + if (!RunningOnValgrind()) { + current_instance = implementation; + } +} + +// ----------------------------------------------------------------------- +// Heap sampling support +// ----------------------------------------------------------------------- + +namespace { + +// Accessors +uintptr_t Count(void** entry) { + return reinterpret_cast<uintptr_t>(entry[0]); +} +uintptr_t Size(void** entry) { + return reinterpret_cast<uintptr_t>(entry[1]); +} +uintptr_t Depth(void** entry) { + return reinterpret_cast<uintptr_t>(entry[2]); +} +void* PC(void** entry, int i) { + return entry[3+i]; +} + +void PrintCountAndSize(MallocExtensionWriter* writer, + uintptr_t count, uintptr_t size) { + char buf[100]; + snprintf(buf, sizeof(buf), + "%6lld: %8lld [%6lld: %8lld] @", + static_cast<long long>(count), + static_cast<long long>(size), + static_cast<long long>(count), + static_cast<long long>(size)); + writer->append(buf, strlen(buf)); +} + +void PrintHeader(MallocExtensionWriter* writer, + const char* label, void** entries) { + // Compute the total count and total size + uintptr_t total_count = 0; + uintptr_t total_size = 0; + for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) { + total_count += Count(entry); + total_size += Size(entry); + } + + const char* const kTitle = "heap profile: "; + writer->append(kTitle, strlen(kTitle)); + PrintCountAndSize(writer, total_count, total_size); + writer->append(" ", 1); + writer->append(label, strlen(label)); + writer->append("\n", 1); +} + +void PrintStackEntry(MallocExtensionWriter* writer, void** entry) { + PrintCountAndSize(writer, Count(entry), Size(entry)); + + for (int i = 0; i < Depth(entry); i++) { + char buf[32]; + snprintf(buf, sizeof(buf), " %p", PC(entry, i)); + writer->append(buf, strlen(buf)); + } + writer->append("\n", 1); +} + +} + +void MallocExtension::GetHeapSample(MallocExtensionWriter* writer) { + int sample_period = 0; + void** entries = ReadStackTraces(&sample_period); + if (entries == NULL) { + const char* const kErrorMsg = + "This malloc implementation does not support sampling.\n" + "As of 2005/01/26, only tcmalloc supports sampling, and\n" + "you are probably running a binary that does not use\n" + "tcmalloc.\n"; + writer->append(kErrorMsg, strlen(kErrorMsg)); + return; + } + + char label[32]; + sprintf(label, "heap_v2/%d", sample_period); + PrintHeader(writer, label, entries); + for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) { + PrintStackEntry(writer, entry); + } + delete[] entries; + + DumpAddressMap(writer); +} + +void MallocExtension::GetHeapGrowthStacks(MallocExtensionWriter* writer) { + void** entries = ReadHeapGrowthStackTraces(); + if (entries == NULL) { + const char* const kErrorMsg = + "This malloc implementation does not support " + "ReadHeapGrowthStackTraces().\n" + "As of 2005/09/27, only tcmalloc supports this, and you\n" + "are probably running a binary that does not use tcmalloc.\n"; + writer->append(kErrorMsg, strlen(kErrorMsg)); + return; + } + + // Do not canonicalize the stack entries, so that we get a + // time-ordered list of stack traces, which may be useful if the + // client wants to focus on the latest stack traces. + PrintHeader(writer, "growth", entries); + for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) { + PrintStackEntry(writer, entry); + } + delete[] entries; + + DumpAddressMap(writer); +} + +// These are C shims that work on the current instance. + +#define C_SHIM(fn, retval, paramlist, arglist) \ + extern "C" PERFTOOLS_DLL_DECL retval MallocExtension_##fn paramlist { \ + return MallocExtension::instance()->fn arglist; \ + } + +C_SHIM(VerifyAllMemory, bool, (), ()); +C_SHIM(VerifyNewMemory, bool, (void* p), (p)); +C_SHIM(VerifyArrayNewMemory, bool, (void* p), (p)); +C_SHIM(VerifyMallocMemory, bool, (void* p), (p)); +C_SHIM(MallocMemoryStats, bool, + (int* blocks, size_t* total, int histogram[kMallocHistogramSize]), + (blocks, total, histogram)); + +C_SHIM(GetStats, void, + (char* buffer, int buffer_length), (buffer, buffer_length)); +C_SHIM(GetNumericProperty, bool, + (const char* property, size_t* value), (property, value)); +C_SHIM(SetNumericProperty, bool, + (const char* property, size_t value), (property, value)); + +C_SHIM(MarkThreadIdle, void, (), ()); +C_SHIM(ReleaseFreeMemory, void, (), ()); +C_SHIM(GetEstimatedAllocatedSize, size_t, (size_t size), (size)); +C_SHIM(GetAllocatedSize, size_t, (void* p), (p)); diff --git a/third_party/tcmalloc/tcmalloc.cc b/third_party/tcmalloc/tcmalloc.cc index e3bbb81..6853eba 100644 --- a/third_party/tcmalloc/tcmalloc.cc +++ b/third_party/tcmalloc/tcmalloc.cc @@ -616,6 +616,11 @@ class TCMallocImplementation : public MallocExtension { Static::pageheap()->ReleaseFreePages(); } + virtual void Scavenge() { + SpinLockHolder h(Static::pageheap_lock()); + Static::pageheap()->Scavenge(); + } + virtual void SetMemoryReleaseRate(double rate) { FLAGS_tcmalloc_release_rate = rate; } diff --git a/third_party/tcmalloc/tcmalloc.gyp b/third_party/tcmalloc/tcmalloc.gyp index ddc85ee..d3fdb39 100644 --- a/third_party/tcmalloc/tcmalloc.gyp +++ b/third_party/tcmalloc/tcmalloc.gyp @@ -44,6 +44,13 @@ }, }, }, + 'conditions': [ + ['OS=="win"', { + 'defines': [ + ['PERFTOOLS_DLL_DECL', ''] + ], + }], + ], }, 'sources': [ 'config.h', @@ -70,7 +77,6 @@ 'tcmalloc/src/internal_logging.cc', 'tcmalloc/src/internal_logging.h', 'tcmalloc/src/linked_list.h', - 'tcmalloc/src/malloc_extension.cc', 'tcmalloc/src/malloc_hook.cc', 'tcmalloc/src/malloc_hook-inl.h', 'tcmalloc/src/page_heap.cc', @@ -120,6 +126,8 @@ # tcmalloc forked files 'allocator_shim.cc', 'generic_allocators.cc', + 'malloc_extension.cc', + 'google/malloc_extension.h', 'page_heap.cc', 'page_heap.h', 'port.cc', @@ -141,6 +149,8 @@ 'generic_allocators.cc', 'tcmalloc.cc', 'win_allocator.cc', + 'tcmalloc/src/malloc_extension.cc', + 'tcmalloc/src/google/malloc_extension.h', ], 'msvs_settings': { # TODO(sgk): merge this with build/common.gypi settings @@ -164,6 +174,9 @@ }, 'conditions': [ ['OS=="win"', { + 'defines': [ + ['PERFTOOLS_DLL_DECL', ''] + ], 'dependencies': [ 'libcmt', ], |