blob: 44033f02d7691bc5a24d76143d650c185e0978ec [file] [log] [blame]
Austin Schuh745610d2015-09-06 18:19:50 -07001// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2// Copyright (c) 2007, Google Inc.
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30//
31// ---
32// Author: Sanjay Ghemawat
33// Chris Demetriou (refactoring)
34//
35// Collect profiling data.
36//
37// The profile data file format is documented in
38// doc/cpuprofile-fileformat.html
39
40
41#ifndef BASE_PROFILEDATA_H_
42#define BASE_PROFILEDATA_H_
43
44#include <config.h>
45#include <time.h> // for time_t
46#include <stdint.h>
47#include "base/basictypes.h"
48
49// A class that accumulates profile samples and writes them to a file.
50//
51// Each sample contains a stack trace and a count. Memory usage is
52// reduced by combining profile samples that have the same stack trace
53// by adding up the associated counts.
54//
55// Profile data is accumulated in a bounded amount of memory, and will
56// flushed to a file as necessary to stay within the memory limit.
57//
58// Use of this class assumes external synchronization. The exact
59// requirements of that synchronization are that:
60//
61// - 'Add' may be called from asynchronous signals, but is not
62// re-entrant.
63//
64// - None of 'Start', 'Stop', 'Reset', 'Flush', and 'Add' may be
65// called at the same time.
66//
67// - 'Start', 'Stop', or 'Reset' should not be called while 'Enabled'
68// or 'GetCurrent' are running, and vice versa.
69//
70// A profiler which uses asyncronous signals to add samples will
71// typically use two locks to protect this data structure:
72//
73// - A SpinLock which is held over all calls except for the 'Add'
74// call made from the signal handler.
75//
76// - A SpinLock which is held over calls to 'Start', 'Stop', 'Reset',
77// 'Flush', and 'Add'. (This SpinLock should be acquired after
78// the first SpinLock in all cases where both are needed.)
79class ProfileData {
80 public:
81 struct State {
82 bool enabled; // Is profiling currently enabled?
83 time_t start_time; // If enabled, when was profiling started?
84 char profile_name[1024]; // Name of file being written, or '\0'
85 int samples_gathered; // Number of samples gathered to far (or 0)
86 };
87
88 class Options {
89 public:
90 Options();
91
92 // Get and set the sample frequency.
93 int frequency() const {
94 return frequency_;
95 }
96 void set_frequency(int frequency) {
97 frequency_ = frequency;
98 }
99
100 private:
101 int frequency_; // Sample frequency.
102 };
103
104 static const int kMaxStackDepth = 64; // Max stack depth stored in profile
105
106 ProfileData();
107 ~ProfileData();
108
109 // If data collection is not already enabled start to collect data
110 // into fname. Parameters related to this profiling run are specified
111 // by 'options'.
112 //
113 // Returns true if data collection could be started, otherwise (if an
114 // error occurred or if data collection was already enabled) returns
115 // false.
116 bool Start(const char *fname, const Options& options);
117
118 // If data collection is enabled, stop data collection and write the
119 // data to disk.
120 void Stop();
121
122 // Stop data collection without writing anything else to disk, and
123 // discard any collected data.
124 void Reset();
125
126 // If data collection is enabled, record a sample with 'depth'
127 // entries from 'stack'. (depth must be > 0.) At most
128 // kMaxStackDepth stack entries will be recorded, starting with
129 // stack[0].
130 //
131 // This function is safe to call from asynchronous signals (but is
132 // not re-entrant).
133 void Add(int depth, const void* const* stack);
134
135 // If data collection is enabled, write the data to disk (and leave
136 // the collector enabled).
137 void FlushTable();
138
139 // Is data collection currently enabled?
140 bool enabled() const { return out_ >= 0; }
141
142 // Get the current state of the data collector.
143 void GetCurrentState(State* state) const;
144
145 private:
146 static const int kAssociativity = 4; // For hashtable
147 static const int kBuckets = 1 << 10; // For hashtable
148 static const int kBufferLength = 1 << 18; // For eviction buffer
149
150 // Type of slots: each slot can be either a count, or a PC value
151 typedef uintptr_t Slot;
152
153 // Hash-table/eviction-buffer entry (a.k.a. a sample)
154 struct Entry {
155 Slot count; // Number of hits
156 Slot depth; // Stack depth
157 Slot stack[kMaxStackDepth]; // Stack contents
158 };
159
160 // Hash table bucket
161 struct Bucket {
162 Entry entry[kAssociativity];
163 };
164
165 Bucket* hash_; // hash table
166 Slot* evict_; // evicted entries
167 int num_evicted_; // how many evicted entries?
168 int out_; // fd for output file.
169 int count_; // How many samples recorded
170 int evictions_; // How many evictions
171 size_t total_bytes_; // How much output
172 char* fname_; // Profile file name
173 time_t start_time_; // Start time, or 0
174
175 // Move 'entry' to the eviction buffer.
176 void Evict(const Entry& entry);
177
178 // Write contents of eviction buffer to disk.
179 void FlushEvicted();
180
181 DISALLOW_COPY_AND_ASSIGN(ProfileData);
182};
183
184#endif // BASE_PROFILEDATA_H_