2 +----------------------------------------------------------------------+
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"
27 ///////////////////////////////////////////////////////////////////////////////
29 // Frame data gathered on function enter/exit.
30 // TODO(#4489053) Should look into reducing size
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
{
48 explicit XDebugProfiler() {}
50 if (m_profilingEnabled
) {
51 writeProfilingResults();
53 if (m_tracingEnabled
) {
56 smart_free(m_frameBuffer
);
59 // Returns true if profiling is required by the extension settings or the
61 static inline bool isProfilingNeeded() {
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
70 static inline bool isTracingNeeded() {
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() {
80 XDEBUG_GLOBAL(CollectTime
) ||
81 XDEBUG_GLOBAL(CollectMemory
) ||
82 isProfilingNeeded() ||
86 // Whether or not the profiler is collecting data
87 inline bool isCollecting() {
88 return m_profilingEnabled
|| m_tracingEnabled
|| m_collectMemory
||
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
,
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
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
{
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
,
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
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
;
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_