Added xdebug computerized tracing output
[hiphop-php.git] / hphp / runtime / ext / xdebug / xdebug_profiler.h
blob732cc526a43b4966ba6050ca0329e19e3c2f0f45
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
6 | Copyright (c) 1997-2010 The PHP Group |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
18 #ifndef incl_HPHP_XDEBUG_PROFILER_H_
19 #define incl_HPHP_XDEBUG_PROFILER_H_
21 #include "hphp/runtime/ext/xdebug/ext_xdebug.h"
22 #include "hphp/runtime/ext/xdebug/xdebug_utils.h"
24 #include "hphp/runtime/ext/ext_hotprofiler.h"
26 namespace HPHP {
27 ///////////////////////////////////////////////////////////////////////////////
29 // Frame data gathered on function enter/exit.
30 // TODO(#4489053) Should look into reducing size
31 struct FrameData {
32 const Func* func;
33 int64_t time;
34 Offset line; // For begin frames, the line called from
35 // We don't need all 64 bits for memory_usage and we need to save space as
36 // this struct is massive and we allocate a ton of them. The TraceProfiler
37 // in ext_hotprofiler.cpp does the same.
38 int64_t memory_usage : 63;
39 bool is_func_begin : 1; // Whether or not this is an enter event
40 // If is_func_begin, then this will be the serialized aruments. Otherwise it
41 // will be the serialized return value
42 const StringData* context_str;
45 // TODO(#4489053) consider allowing user to set the maximum buffer size
46 class XDebugProfiler : public Profiler {
47 public:
48 explicit XDebugProfiler() {}
49 ~XDebugProfiler() {
50 if (m_profilingEnabled) {
51 writeProfilingResults();
53 if (m_tracingEnabled) {
54 disableTracing();
56 smart_free(m_frameBuffer);
59 // Returns true if profiling is required by the extension settings or the
60 // environment
61 static inline bool isProfilingNeeded() {
62 return
63 XDEBUG_GLOBAL(ProfilerEnable) ||
64 (XDEBUG_GLOBAL(ProfilerEnableTrigger) &&
65 XDebugUtils::isTriggerSet("XDEBUG_TRACE"));
68 // Returns true if tracing is required by the extension settings or the
69 // environment
70 static inline bool isTracingNeeded() {
71 return
72 XDEBUG_GLOBAL(AutoTrace) ||
73 (XDEBUG_GLOBAL(TraceEnableTrigger) &&
74 XDebugUtils::isTriggerSet("XDEBUG_TRACE"));
77 // Returns true if a profiler should be attached to the current thread
78 static inline bool isNeeded() {
79 return
80 XDEBUG_GLOBAL(CollectTime) ||
81 XDEBUG_GLOBAL(CollectMemory) ||
82 isProfilingNeeded() ||
83 isTracingNeeded();
86 // Whether or not the profiler is collecting data
87 inline bool isCollecting() {
88 return m_profilingEnabled || m_tracingEnabled || m_collectMemory ||
89 m_collectTime;
92 // Set memory/time collecting
93 inline void setCollectMemory(bool collect) { m_collectMemory = collect; }
94 inline void setCollectTime(bool collect) { m_collectTime = collect; }
96 // Enables profiling. Profiling cannot be disabled.
97 void enableProfiling(const String& filename, int64_t opts);
98 inline bool isProfiling() { return m_profilingEnabled; }
99 inline const String getProfilingFilename() {
100 return m_profilingEnabled ? m_profilingFilename : empty_string();
103 // Enable/disable tracing
104 void enableTracing(const String& filename, int64_t opts);
105 void disableTracing();
106 inline bool isTracing() { return m_tracingEnabled; }
107 inline const String getTracingFilename() {
108 return m_tracingEnabled ? m_tracingFilename : empty_string();
111 // Functions called on frame begin/end
112 virtual void beginFrame(const char* symbol);
113 virtual void endFrame(const TypedValue* retVal,
114 const char* symbol,
115 bool endMain = false);
116 virtual inline void endAllFrames() {}
118 // xdebug has no need to write stats to php array
119 virtual inline void writeStats(Array &ret) {}
121 // TODO (#4489053) Iteration up the stack
122 inline void begin() XDEBUG_NOTIMPLEMENTED
123 inline void end() XDEBUG_NOTIMPLEMENTED
124 private:
125 // Allocates more buffer space if needed, otherwise does nothing.
126 // On failure, a human-readable error is thrown.
127 void ensureBufferSpace();
129 // Populates the passed frame data. All fields should be filled, because
130 // the passed frameData is filled with junk.
131 virtual void collectFrameData(FrameData& frameData, const TypedValue* retVal);
133 // Helper for begin/end frame that grabs the next frame data and populates it
134 // If retVal is null, this is a begin frame. Otherwise this is a frame end
135 // event and retVal is the returned value
136 void recordFrame(const TypedValue* retVal);
138 // Helper used to convert a microseconds since epoch into the format xdebug
139 // uses: microseconds since request init, as a double
140 inline double timeSinceBase(int64_t time) {
141 return (time - XDEBUG_GLOBAL(InitTime)) * 1.0e-6;
144 // The different types of tracefile output
145 enum class TraceOutputType {
146 NORMAL,
147 COMPUTERIZED,
148 HTML
151 // Write the tracing results in normal/computerized/html format. A template is
152 // used to prevent unnecessary runtime casing.
153 template <TraceOutputType outputType>
154 void writeTracingResults();
156 template <TraceOutputType outputType>
157 void writeTracingResultsHeader();
159 template <TraceOutputType outputType>
160 void writeTracingResultsFooter();
162 // Write a given frame in normal/computerized/html format. The frame is at
163 // stack level level and its' begin frame starts at startIdx in the internal
164 // buffer. Its parent begin frame is passed. Returns the index of the frame's
165 // end frame in the internal buffer, or -1 if there was no end frame.
166 template <TraceOutputType outputType>
167 int64_t writeTracingFrame(int64_t level,
168 int64_t startIdx,
169 const FrameData* parentBegin);
171 template <TraceOutputType outputType>
172 void writeTracingLinePrefix();
174 template <TraceOutputType outputType>
175 void writeTracingLevel(int64_t level);
177 template <TraceOutputType outputType>
178 void writeTracingFrameId(uint64_t id);
180 template <TraceOutputType outputType>
181 void writeTracingTime(int64_t time);
183 template<TraceOutputType outputType>
184 void writeTracingMemory(int64_t memory);
186 template <TraceOutputType outputType>
187 void writeTracingIndent(int64_t level);
189 void writeTracingFuncName(const Func* func, bool isTopPseudoMain);
191 template<TraceOutputType outputType>
192 void writeTracingFunc(FrameData& frame, bool isTopPseudoMain);
194 template <TraceOutputType outputType>
195 void writeTracingCallsite(FrameData& frame, const FrameData* parent);
197 template <TraceOutputType outputType>
198 void writeTracingLineSuffix();
200 template <TraceOutputType outputType>
201 void writeTracingEndFrame(FrameData& frame, int64_t level, int64_t id);
203 // Used when we have both the beginning and end frame data
204 struct Frame {
205 FrameData& begin;
206 FrameData& end;
207 explicit Frame(FrameData& beginFrame, FrameData& endFrame)
208 : begin(beginFrame), end(endFrame) {}
211 // Called on profiler destruction, writes the profiling results.
212 void writeProfilingResults();
214 // Writes a stack frame's profiling information to the profiling file. The
215 // frame's begin frame data starts at startIdx in the internal buffer. Returns
216 // the index in the internal buffer of the frame's end frame data or -1 if
217 // an error occurred.
218 int64_t writeProfilingFrame(int64_t startIdx);
220 // Writes the given frame in cachegrind format to the given file
221 void writeCachegrindFrame(const Frame& frame,
222 const std::vector<Frame>& children,
223 int64_t childrenCost,
224 bool isTopPseudoMain);
226 // Writes the given function's filename in cachegrind format
227 void writeCachegrindFuncFileName(const Func* func);
229 // Writes the given function's name in cachegrind format
230 void writeCachegrindFuncName(const Func* func, bool isTopPseudoMain);
232 FrameData* m_frameBuffer = nullptr;
233 int64_t m_frameBufferSize = 0;
234 int64_t m_nextFrameIdx = 0;
236 bool m_collectMemory = false;
237 bool m_collectTime = false;
239 bool m_profilingEnabled = false;
240 int64_t m_profilingOpts = 0;
241 String m_profilingFilename;
242 FILE* m_profilingFile;
244 bool m_tracingEnabled = false;
245 int64_t m_tracingOpts = 0;
246 int64_t m_tracingStartIdx = 0;
247 std::vector<FrameData> m_tracingStartFrameData;
248 String m_tracingFilename;
249 FILE* m_tracingFile;
251 // When writing the tracing file in computerized and html output we need to
252 // assign each begin/end frame pair an id.
253 uint64_t m_tracingNextFrameId = 0;
255 // When writing the tracing file with show_mem_delta we need a reference to
256 // the previous begin frame
257 FrameData* m_tracingPrevBegin = nullptr;
260 ///////////////////////////////////////////////////////////////////////////////
263 #endif // incl_HPHP_XDEBUG_PROFILER_H_