Add logging for comparison behaviors
[hiphop-php.git] / hphp / util / stacktrace-profiler.h
blobbac4fc612cea82147daedeea1faa17f0098c5e36
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_PROBE_H
18 #define incl_HPHP_PROBE_H
20 #include <string>
21 #include <mutex>
22 #include <atomic>
23 #include "hphp/util/arena.h"
25 namespace HPHP {
28 * One single stack trace sample. These can be generated, stored,
29 * then passed to a StackTraceProfiler after the fact.
31 struct StackTraceSample {
32 static const int kMaxDepth = 10;
33 StackTraceSample();
34 int depth;
35 void* addrs[kMaxDepth];
39 * A StackTraceProfiler incrementally constructs a prof-style caller tree from
40 * the native backtrace each time its count() method is called, then dumps the
41 * tree to stderr when destructed.
43 * Example usage to get two value profiles based on a bool:
44 * void myTweakedFunction(bool personality=false) {
45 * static StackTraceProfiler prof_true("myCoolFunction-true");
46 * static StackTraceProfiler prof_false("myCoolFunction-false");
47 * (personality ? &prof_true : &prof_false)->count();
48 * }
50 * Sometimes it is useful to disable inlining & tail-calls to make
51 * stack traces easier to understand:
52 * -O2 -fno-inline -fno-optimize-sibling-calls
54 struct StackTraceProfiler {
55 private:
56 struct Node {
57 explicit Node(void* addr) :
58 addr(addr), callers(nullptr), next(nullptr), hits(0) {
60 void* const addr;
61 Node* callers;
62 Node* next;
63 size_t hits;
66 public:
67 explicit StackTraceProfiler(std::string name, int skip = 1);
68 ~StackTraceProfiler();
69 StackTraceProfiler(const StackTraceProfiler& other) = delete;
70 StackTraceProfiler& operator=(const StackTraceProfiler& other) = delete;
72 // count one call in this probe.
73 void count();
74 void count(const StackTraceSample&);
75 size_t hits() const { return m_root.hits; }
77 private:
78 static bool compareNodes(Node* a, Node* b);
79 Node* findCaller(Node* n, void* addr);
80 Node* makeCaller(Node* n, void* addr);
81 void print(Node* n, std::string indent);
82 int numLeaves(Node* n);
84 private:
85 Arena m_arena;
86 const std::string m_name;
87 std::mutex m_mutex;
88 std::atomic<bool> finishing;
89 Node m_root;
90 int m_skip;
94 * BoolProfiler is used to collect profiled samples of a bool variable.
96 struct BoolProfiler {
97 explicit BoolProfiler(std::string name);
98 ~BoolProfiler();
99 bool operator()(bool b);
100 private:
101 const std::string name;
102 StackTraceProfiler p1, p0;
106 * IntProfiler is used to collect profiled samples of an unsiged variable.
107 * A histogram of samples are collected in power-of-2 buckets up to 64.
109 struct IntProfiler {
110 explicit IntProfiler(std::string name);
111 ~IntProfiler();
112 void operator()(unsigned i);
113 private:
114 const std::string name;
115 StackTraceProfiler pN, p64, p32, p16, p8, p4, p2, p1, p0;
118 extern std::atomic<bool> enable_stacktrace_profiler;
122 #endif