|
16 | 16 | * SPDX-License-Identifier: Apache-2.0 |
17 | 17 | */ |
18 | 18 |
|
| 19 | +#include <sys/sysinfo.h> |
| 20 | + |
19 | 21 | #include <csignal> |
20 | 22 | #include <iostream> |
21 | 23 | #include <thread> |
22 | 24 |
|
23 | 25 | #include "src/common/base/base.h" |
| 26 | +#include "src/shared/pprof/pprof.h" |
24 | 27 | #include "src/shared/upid/upid.h" |
25 | 28 | #include "src/stirling/core/unit_connector.h" |
26 | 29 | #include "src/stirling/source_connectors/perf_profiler/perf_profile_connector.h" |
27 | | -#include "src/stirling/source_connectors/perf_profiler/stack_traces_table.h" |
28 | 30 |
|
29 | 31 | using ::px::Status; |
30 | 32 |
|
31 | 33 | DEFINE_uint32(time, 30, "Number of seconds to run the profiler."); |
| 34 | +DEFINE_string(pprof_pb_file, "profile.pb", "File path for pprof protobuf output."); |
| 35 | +DECLARE_uint32(stirling_profiler_stack_trace_sample_period_ms); |
32 | 36 |
|
33 | 37 | namespace px { |
34 | 38 | namespace stirling { |
35 | 39 |
|
36 | 40 | class Profiler : public UnitConnector<PerfProfileConnector> { |
37 | 41 | public: |
38 | | - Status PrintData() { |
39 | | - // Build the stack traces histogram. |
| 42 | + Status WritePProf() { |
| 43 | + // Build stack traces histogram. |
40 | 44 | PX_RETURN_IF_ERROR(BuildHistogram()); |
41 | 45 |
|
42 | | - // Print the stack traces histogram. |
43 | | - // TODO(jps): replace this with a pprof proto file writer. |
44 | | - // 15x: libc.so;main;foo;bar |
45 | | - // 12x: libc.so;main;foo;qux |
46 | | - for (const auto& [str, count] : histo_) { |
47 | | - LOG(INFO) << count << "x: " << str; |
| 46 | + // Create the pprof profile. |
| 47 | + const uint32_t num_cpus = get_nprocs_conf(); |
| 48 | + const uint32_t period_ms = FLAGS_stirling_profiler_stack_trace_sample_period_ms; |
| 49 | + const auto pprof_pb = px::shared::CreatePProfProfile(num_cpus, period_ms, histo_); |
| 50 | + |
| 51 | + // Write the pprof profile to disk. |
| 52 | + std::fstream outfile(FLAGS_pprof_pb_file, std::ios::out | std::ios::trunc | std::ios::binary); |
| 53 | + if (!outfile.is_open()) { |
| 54 | + char const* const err_msg = "Failed to open output file: $0."; |
| 55 | + return error::Internal(absl::Substitute(err_msg, FLAGS_pprof_pb_file)); |
| 56 | + } |
| 57 | + |
| 58 | + if (!pprof_pb.SerializeToOstream(&outfile)) { |
| 59 | + char const* const err_msg = "Failed to write pprof protobuf to file: $0."; |
| 60 | + return error::Internal(absl::Substitute(err_msg, FLAGS_pprof_pb_file)); |
48 | 61 | } |
49 | 62 | return Status::OK(); |
50 | 63 | } |
@@ -101,8 +114,8 @@ Status RunProfiler() { |
101 | 114 | // Stop collecting data and do a final read out of eBPF perf buffer & maps. |
102 | 115 | PX_RETURN_IF_ERROR(g_profiler->Stop()); |
103 | 116 |
|
104 | | - // Print the info. We will replace this with a pprof proto file write out. |
105 | | - PX_RETURN_IF_ERROR(g_profiler->PrintData()); |
| 117 | + // Write a pprof proto file. |
| 118 | + PX_RETURN_IF_ERROR(g_profiler->WritePProf()); |
106 | 119 |
|
107 | 120 | // Phew. We are outta here. |
108 | 121 | return Status::OK(); |
|
0 commit comments