diff options
Diffstat (limited to 'src/third_party/gperftools-2.5/src/profiledata.cc')
-rw-r--r-- | src/third_party/gperftools-2.5/src/profiledata.cc | 332 |
1 files changed, 0 insertions, 332 deletions
diff --git a/src/third_party/gperftools-2.5/src/profiledata.cc b/src/third_party/gperftools-2.5/src/profiledata.cc deleted file mode 100644 index 8b05d3aa45c..00000000000 --- a/src/third_party/gperftools-2.5/src/profiledata.cc +++ /dev/null @@ -1,332 +0,0 @@ -// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- -// Copyright (c) 2007, 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 -// Chris Demetriou (refactoring) -// -// Collect profiling data. - -#include <config.h> -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#include <sys/time.h> -#include <string.h> -#include <fcntl.h> - -#include "profiledata.h" - -#include "base/logging.h" -#include "base/sysinfo.h" - -// All of these are initialized in profiledata.h. -const int ProfileData::kMaxStackDepth; -const int ProfileData::kAssociativity; -const int ProfileData::kBuckets; -const int ProfileData::kBufferLength; - -ProfileData::Options::Options() - : frequency_(1) { -} - -// This function is safe to call from asynchronous signals (but is not -// re-entrant). However, that's not part of its public interface. -void ProfileData::Evict(const Entry& entry) { - const int d = entry.depth; - const int nslots = d + 2; // Number of slots needed in eviction buffer - if (num_evicted_ + nslots > kBufferLength) { - FlushEvicted(); - assert(num_evicted_ == 0); - assert(nslots <= kBufferLength); - } - evict_[num_evicted_++] = entry.count; - evict_[num_evicted_++] = d; - memcpy(&evict_[num_evicted_], entry.stack, d * sizeof(Slot)); - num_evicted_ += d; -} - -ProfileData::ProfileData() - : hash_(0), - evict_(0), - num_evicted_(0), - out_(-1), - count_(0), - evictions_(0), - total_bytes_(0), - fname_(0), - start_time_(0) { -} - -bool ProfileData::Start(const char* fname, - const ProfileData::Options& options) { - if (enabled()) { - return false; - } - - // Open output file and initialize various data structures - int fd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, 0666); - if (fd < 0) { - // Can't open outfile for write - return false; - } - - start_time_ = time(NULL); - fname_ = strdup(fname); - - // Reset counters - num_evicted_ = 0; - count_ = 0; - evictions_ = 0; - total_bytes_ = 0; - - hash_ = new Bucket[kBuckets]; - evict_ = new Slot[kBufferLength]; - memset(hash_, 0, sizeof(hash_[0]) * kBuckets); - - // Record special entries - evict_[num_evicted_++] = 0; // count for header - evict_[num_evicted_++] = 3; // depth for header - evict_[num_evicted_++] = 0; // Version number - CHECK_NE(0, options.frequency()); - int period = 1000000 / options.frequency(); - evict_[num_evicted_++] = period; // Period (microseconds) - evict_[num_evicted_++] = 0; // Padding - - out_ = fd; - - return true; -} - -ProfileData::~ProfileData() { - Stop(); -} - -// Dump /proc/maps data to fd. Copied from heap-profile-table.cc. -#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR) - -static void FDWrite(int fd, const char* buf, size_t len) { - while (len > 0) { - ssize_t r; - NO_INTR(r = write(fd, buf, len)); - RAW_CHECK(r >= 0, "write failed"); - buf += r; - len -= r; - } -} - -static void DumpProcSelfMaps(int fd) { - ProcMapsIterator::Buffer iterbuf; - ProcMapsIterator it(0, &iterbuf); // 0 means "current pid" - - uint64 start, end, offset; - int64 inode; - char *flags, *filename; - ProcMapsIterator::Buffer linebuf; - while (it.Next(&start, &end, &flags, &offset, &inode, &filename)) { - int written = it.FormatLine(linebuf.buf_, sizeof(linebuf.buf_), - start, end, flags, offset, inode, filename, - 0); - FDWrite(fd, linebuf.buf_, written); - } -} - -void ProfileData::Stop() { - if (!enabled()) { - return; - } - - // Move data from hash table to eviction buffer - for (int b = 0; b < kBuckets; b++) { - Bucket* bucket = &hash_[b]; - for (int a = 0; a < kAssociativity; a++) { - if (bucket->entry[a].count > 0) { - Evict(bucket->entry[a]); - } - } - } - - if (num_evicted_ + 3 > kBufferLength) { - // Ensure there is enough room for end of data marker - FlushEvicted(); - } - - // Write end of data marker - evict_[num_evicted_++] = 0; // count - evict_[num_evicted_++] = 1; // depth - evict_[num_evicted_++] = 0; // end of data marker - FlushEvicted(); - - // Dump "/proc/self/maps" so we get list of mapped shared libraries - DumpProcSelfMaps(out_); - - Reset(); - fprintf(stderr, "PROFILE: interrupts/evictions/bytes = %d/%d/%" PRIuS "\n", - count_, evictions_, total_bytes_); -} - -void ProfileData::Reset() { - if (!enabled()) { - return; - } - - // Don't reset count_, evictions_, or total_bytes_ here. They're used - // by Stop to print information about the profile after reset, and are - // cleared by Start when starting a new profile. - close(out_); - delete[] hash_; - hash_ = 0; - delete[] evict_; - evict_ = 0; - num_evicted_ = 0; - free(fname_); - fname_ = 0; - start_time_ = 0; - - out_ = -1; -} - -// This function is safe to call from asynchronous signals (but is not -// re-entrant). However, that's not part of its public interface. -void ProfileData::GetCurrentState(State* state) const { - if (enabled()) { - state->enabled = true; - state->start_time = start_time_; - state->samples_gathered = count_; - int buf_size = sizeof(state->profile_name); - strncpy(state->profile_name, fname_, buf_size); - state->profile_name[buf_size-1] = '\0'; - } else { - state->enabled = false; - state->start_time = 0; - state->samples_gathered = 0; - state->profile_name[0] = '\0'; - } -} - -// This function is safe to call from asynchronous signals (but is not -// re-entrant). However, that's not part of its public interface. -void ProfileData::FlushTable() { - if (!enabled()) { - return; - } - - // Move data from hash table to eviction buffer - for (int b = 0; b < kBuckets; b++) { - Bucket* bucket = &hash_[b]; - for (int a = 0; a < kAssociativity; a++) { - if (bucket->entry[a].count > 0) { - Evict(bucket->entry[a]); - bucket->entry[a].depth = 0; - bucket->entry[a].count = 0; - } - } - } - - // Write out all pending data - FlushEvicted(); -} - -void ProfileData::Add(int depth, const void* const* stack) { - if (!enabled()) { - return; - } - - if (depth > kMaxStackDepth) depth = kMaxStackDepth; - RAW_CHECK(depth > 0, "ProfileData::Add depth <= 0"); - - // Make hash-value - Slot h = 0; - for (int i = 0; i < depth; i++) { - Slot slot = reinterpret_cast<Slot>(stack[i]); - h = (h << 8) | (h >> (8*(sizeof(h)-1))); - h += (slot * 31) + (slot * 7) + (slot * 3); - } - - count_++; - - // See if table already has an entry for this trace - bool done = false; - Bucket* bucket = &hash_[h % kBuckets]; - for (int a = 0; a < kAssociativity; a++) { - Entry* e = &bucket->entry[a]; - if (e->depth == depth) { - bool match = true; - for (int i = 0; i < depth; i++) { - if (e->stack[i] != reinterpret_cast<Slot>(stack[i])) { - match = false; - break; - } - } - if (match) { - e->count++; - done = true; - break; - } - } - } - - if (!done) { - // Evict entry with smallest count - Entry* e = &bucket->entry[0]; - for (int a = 1; a < kAssociativity; a++) { - if (bucket->entry[a].count < e->count) { - e = &bucket->entry[a]; - } - } - if (e->count > 0) { - evictions_++; - Evict(*e); - } - - // Use the newly evicted entry - e->depth = depth; - e->count = 1; - for (int i = 0; i < depth; i++) { - e->stack[i] = reinterpret_cast<Slot>(stack[i]); - } - } -} - -// This function is safe to call from asynchronous signals (but is not -// re-entrant). However, that's not part of its public interface. -void ProfileData::FlushEvicted() { - if (num_evicted_ > 0) { - const char* buf = reinterpret_cast<char*>(evict_); - size_t bytes = sizeof(evict_[0]) * num_evicted_; - total_bytes_ += bytes; - FDWrite(out_, buf, bytes); - } - num_evicted_ = 0; -} |