1
#include "source/common/profiler/profiler.h"
2

            
3
#include <string>
4

            
5
#include "source/common/common/thread.h"
6

            
7
#ifdef PROFILER_AVAILABLE
8

            
9
#include "gperftools/heap-profiler.h"
10
#include "gperftools/profiler.h"
11

            
12
namespace Envoy {
13
namespace Profiler {
14

            
15
24
bool Cpu::profilerEnabled() { return ProfilingIsEnabledForAllThreads(); }
16

            
17
11
bool Cpu::startProfiler(const std::string& output_path) {
18
11
  return ProfilerStart(output_path.c_str());
19
11
}
20

            
21
10
void Cpu::stopProfiler() { ProfilerStop(); }
22

            
23
6
bool Heap::profilerEnabled() {
24
  // determined by PROFILER_AVAILABLE
25
6
  return true;
26
6
}
27

            
28
8
bool Heap::isProfilerStarted() { return IsHeapProfilerRunning(); }
29
2
bool Heap::startProfiler(const std::string& output_file_name_prefix) {
30
2
  HeapProfilerStart(output_file_name_prefix.c_str());
31
2
  return true;
32
2
}
33

            
34
3
bool Heap::stopProfiler() {
35
3
  if (!IsHeapProfilerRunning()) {
36
1
    return false;
37
1
  }
38
2
  HeapProfilerDump("stop and dump");
39
2
  HeapProfilerStop();
40
2
  return true;
41
3
}
42

            
43
} // namespace Profiler
44
} // namespace Envoy
45

            
46
#else
47

            
48
namespace Envoy {
49
namespace Profiler {
50

            
51
bool Cpu::profilerEnabled() { return false; }
52
bool Cpu::startProfiler(const std::string&) { return false; }
53
void Cpu::stopProfiler() {}
54

            
55
bool Heap::profilerEnabled() { return false; }
56
bool Heap::isProfilerStarted() { return false; }
57
bool Heap::startProfiler(const std::string&) { return false; }
58
bool Heap::stopProfiler() { return false; }
59

            
60
} // namespace Profiler
61
} // namespace Envoy
62

            
63
#endif // #ifdef PROFILER_AVAILABLE
64

            
65
#ifdef TCMALLOC
66

            
67
#include "tcmalloc/malloc_extension.h"
68
#include "tcmalloc/profile_marshaler.h"
69

            
70
namespace Envoy {
71
namespace Profiler {
72

            
73
static tcmalloc::MallocExtension::AllocationProfilingToken* alloc_profiler = nullptr;
74

            
75
absl::StatusOr<std::string> TcmallocProfiler::tcmallocHeapProfile() {
76
  auto profile = tcmalloc::MallocExtension::SnapshotCurrent(tcmalloc::ProfileType::kHeap);
77
  return tcmalloc::Marshal(profile);
78
}
79

            
80
absl::Status TcmallocProfiler::startAllocationProfile() {
81
  ASSERT_IS_MAIN_OR_TEST_THREAD();
82
  if (alloc_profiler != nullptr) {
83
    return {absl::StatusCode::kFailedPrecondition, "Allocation profiler has already started"};
84
  }
85
  alloc_profiler = new tcmalloc::MallocExtension::AllocationProfilingToken(
86
      tcmalloc::MallocExtension::StartAllocationProfiling());
87
  return absl::OkStatus();
88
}
89

            
90
absl::StatusOr<std::string> TcmallocProfiler::stopAllocationProfile() {
91
  ASSERT_IS_MAIN_OR_TEST_THREAD();
92
  if (!alloc_profiler) {
93
    return absl::Status(absl::StatusCode::kFailedPrecondition,
94
                        "Allocation profiler is not started");
95
  }
96
  const auto profile = std::move(*alloc_profiler).Stop();
97
  const auto result = tcmalloc::Marshal(profile);
98
  delete alloc_profiler;
99
  alloc_profiler = nullptr;
100
  return result;
101
}
102

            
103
} // namespace Profiler
104
} // namespace Envoy
105

            
106
#else
107

            
108
namespace Envoy {
109
namespace Profiler {
110

            
111
1
absl::StatusOr<std::string> TcmallocProfiler::tcmallocHeapProfile() {
112
1
  return absl::Status(absl::StatusCode::kUnimplemented,
113
1
                      "Heap profile is not implemented in current build");
114
1
}
115

            
116
1
absl::Status TcmallocProfiler::startAllocationProfile() {
117
1
  return absl::Status(absl::StatusCode::kUnimplemented,
118
1
                      "Allocation profile is not implemented in current build");
119
1
}
120

            
121
1
absl::StatusOr<std::string> TcmallocProfiler::stopAllocationProfile() {
122
1
  return absl::Status(absl::StatusCode::kUnimplemented,
123
1
                      "Allocation profile is not implemented in current build");
124
1
}
125

            
126
} // namespace Profiler
127
} // namespace Envoy
128

            
129
#endif // #ifdef TCMALLOC