xref: /aosp_15_r20/external/bcc/examples/cpp/pyperf/PyPerf.cc (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker  * PyPerf Profile Python Processes with Python stack-trace.
3*387f9dfdSAndroid Build Coastguard Worker  *        For Linux, uses BCC, eBPF. Embedded C.
4*387f9dfdSAndroid Build Coastguard Worker  *
5*387f9dfdSAndroid Build Coastguard Worker  * Example of using BPF to profile Python Processes with Python stack-trace.
6*387f9dfdSAndroid Build Coastguard Worker  *
7*387f9dfdSAndroid Build Coastguard Worker  * USAGE: PyPerf [-d|--duration DURATION_MS] [-c|--sample-rate SAMPLE_RATE]
8*387f9dfdSAndroid Build Coastguard Worker  *               [-v|--verbosity LOG_VERBOSITY]
9*387f9dfdSAndroid Build Coastguard Worker  *
10*387f9dfdSAndroid Build Coastguard Worker  * Copyright (c) Facebook, Inc.
11*387f9dfdSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License")
12*387f9dfdSAndroid Build Coastguard Worker  */
13*387f9dfdSAndroid Build Coastguard Worker 
14*387f9dfdSAndroid Build Coastguard Worker #include <cinttypes>
15*387f9dfdSAndroid Build Coastguard Worker #include <cstdlib>
16*387f9dfdSAndroid Build Coastguard Worker #include <string>
17*387f9dfdSAndroid Build Coastguard Worker #include <vector>
18*387f9dfdSAndroid Build Coastguard Worker 
19*387f9dfdSAndroid Build Coastguard Worker #include "PyPerfDefaultPrinter.h"
20*387f9dfdSAndroid Build Coastguard Worker #include "PyPerfLoggingHelper.h"
21*387f9dfdSAndroid Build Coastguard Worker #include "PyPerfUtil.h"
22*387f9dfdSAndroid Build Coastguard Worker 
main(int argc,char ** argv)23*387f9dfdSAndroid Build Coastguard Worker int main(int argc, char** argv) {
24*387f9dfdSAndroid Build Coastguard Worker   // Argument parsing helpers
25*387f9dfdSAndroid Build Coastguard Worker   int pos = 1;
26*387f9dfdSAndroid Build Coastguard Worker 
27*387f9dfdSAndroid Build Coastguard Worker   auto parseIntArg = [&](std::vector<std::string> argNames, uint64_t& target) {
28*387f9dfdSAndroid Build Coastguard Worker     std::string arg(argv[pos]);
29*387f9dfdSAndroid Build Coastguard Worker     for (const auto& name : argNames) {
30*387f9dfdSAndroid Build Coastguard Worker       if (arg == name) {
31*387f9dfdSAndroid Build Coastguard Worker         if (pos == argc) {
32*387f9dfdSAndroid Build Coastguard Worker           std::fprintf(stderr, "Expect value after %s\n", arg.c_str());
33*387f9dfdSAndroid Build Coastguard Worker           std::exit(1);
34*387f9dfdSAndroid Build Coastguard Worker         }
35*387f9dfdSAndroid Build Coastguard Worker         pos++;
36*387f9dfdSAndroid Build Coastguard Worker         std::string value(argv[pos]);
37*387f9dfdSAndroid Build Coastguard Worker         try {
38*387f9dfdSAndroid Build Coastguard Worker           target = std::stoi(value);
39*387f9dfdSAndroid Build Coastguard Worker         } catch (const std::exception& e) {
40*387f9dfdSAndroid Build Coastguard Worker           std::fprintf(stderr, "Expect integer value after %s, got %s: %s\n",
41*387f9dfdSAndroid Build Coastguard Worker                        arg.c_str(), value.c_str(), e.what());
42*387f9dfdSAndroid Build Coastguard Worker           std::exit(1);
43*387f9dfdSAndroid Build Coastguard Worker         }
44*387f9dfdSAndroid Build Coastguard Worker         return true;
45*387f9dfdSAndroid Build Coastguard Worker       }
46*387f9dfdSAndroid Build Coastguard Worker     }
47*387f9dfdSAndroid Build Coastguard Worker     return false;
48*387f9dfdSAndroid Build Coastguard Worker   };
49*387f9dfdSAndroid Build Coastguard Worker 
50*387f9dfdSAndroid Build Coastguard Worker   auto parseBoolArg = [&](std::vector<std::string> argNames, bool& target) {
51*387f9dfdSAndroid Build Coastguard Worker     std::string arg(argv[pos]);
52*387f9dfdSAndroid Build Coastguard Worker     for (const auto& name : argNames) {
53*387f9dfdSAndroid Build Coastguard Worker       if (arg == ("--" + name)) {
54*387f9dfdSAndroid Build Coastguard Worker         target = true;
55*387f9dfdSAndroid Build Coastguard Worker         return true;
56*387f9dfdSAndroid Build Coastguard Worker       }
57*387f9dfdSAndroid Build Coastguard Worker       if (arg == "--no-" + name) {
58*387f9dfdSAndroid Build Coastguard Worker         target = false;
59*387f9dfdSAndroid Build Coastguard Worker         return true;
60*387f9dfdSAndroid Build Coastguard Worker       }
61*387f9dfdSAndroid Build Coastguard Worker     }
62*387f9dfdSAndroid Build Coastguard Worker     return false;
63*387f9dfdSAndroid Build Coastguard Worker   };
64*387f9dfdSAndroid Build Coastguard Worker 
65*387f9dfdSAndroid Build Coastguard Worker   // Default argument values
66*387f9dfdSAndroid Build Coastguard Worker   uint64_t sampleRate = 1000000;
67*387f9dfdSAndroid Build Coastguard Worker   uint64_t durationMs = 1000;
68*387f9dfdSAndroid Build Coastguard Worker   uint64_t verbosityLevel = 0;
69*387f9dfdSAndroid Build Coastguard Worker   bool showGILState = true;
70*387f9dfdSAndroid Build Coastguard Worker   bool showThreadState = true;
71*387f9dfdSAndroid Build Coastguard Worker   bool showPthreadIDState = false;
72*387f9dfdSAndroid Build Coastguard Worker 
73*387f9dfdSAndroid Build Coastguard Worker   while (true) {
74*387f9dfdSAndroid Build Coastguard Worker     if (pos >= argc) {
75*387f9dfdSAndroid Build Coastguard Worker       break;
76*387f9dfdSAndroid Build Coastguard Worker     }
77*387f9dfdSAndroid Build Coastguard Worker     bool found = false;
78*387f9dfdSAndroid Build Coastguard Worker     found = found || parseIntArg({"-c", "--sample-rate"}, sampleRate);
79*387f9dfdSAndroid Build Coastguard Worker     found = found || parseIntArg({"-d", "--duration"}, durationMs);
80*387f9dfdSAndroid Build Coastguard Worker     found = found || parseIntArg({"-v", "--verbose"}, verbosityLevel);
81*387f9dfdSAndroid Build Coastguard Worker     found = found || parseBoolArg({"show-gil-state"}, showGILState);
82*387f9dfdSAndroid Build Coastguard Worker     found = found || parseBoolArg({"show-thread-state"}, showThreadState);
83*387f9dfdSAndroid Build Coastguard Worker     found =
84*387f9dfdSAndroid Build Coastguard Worker         found || parseBoolArg({"show-pthread-id-state"}, showPthreadIDState);
85*387f9dfdSAndroid Build Coastguard Worker     if (!found) {
86*387f9dfdSAndroid Build Coastguard Worker       std::fprintf(stderr, "Unexpected argument: %s\n", argv[pos]);
87*387f9dfdSAndroid Build Coastguard Worker       std::exit(1);
88*387f9dfdSAndroid Build Coastguard Worker     }
89*387f9dfdSAndroid Build Coastguard Worker     pos++;
90*387f9dfdSAndroid Build Coastguard Worker   }
91*387f9dfdSAndroid Build Coastguard Worker 
92*387f9dfdSAndroid Build Coastguard Worker   ebpf::pyperf::setVerbosity(verbosityLevel);
93*387f9dfdSAndroid Build Coastguard Worker   ebpf::pyperf::logInfo(1, "Profiling Sample Rate: %" PRIu64 "\n", sampleRate);
94*387f9dfdSAndroid Build Coastguard Worker   ebpf::pyperf::logInfo(1, "Profiling Duration: %" PRIu64 "ms\n", durationMs);
95*387f9dfdSAndroid Build Coastguard Worker   ebpf::pyperf::logInfo(1, "Showing GIL state: %d\n", showGILState);
96*387f9dfdSAndroid Build Coastguard Worker   ebpf::pyperf::logInfo(1, "Showing Thread state: %d\n", showThreadState);
97*387f9dfdSAndroid Build Coastguard Worker   ebpf::pyperf::logInfo(1, "Showing Pthread ID state: %d\n",
98*387f9dfdSAndroid Build Coastguard Worker                         showPthreadIDState);
99*387f9dfdSAndroid Build Coastguard Worker 
100*387f9dfdSAndroid Build Coastguard Worker   ebpf::pyperf::PyPerfUtil util;
101*387f9dfdSAndroid Build Coastguard Worker   util.init();
102*387f9dfdSAndroid Build Coastguard Worker 
103*387f9dfdSAndroid Build Coastguard Worker   ebpf::pyperf::PyPerfDefaultPrinter printer(showGILState, showThreadState,
104*387f9dfdSAndroid Build Coastguard Worker                                              showPthreadIDState);
105*387f9dfdSAndroid Build Coastguard Worker   util.profile(sampleRate, durationMs, &printer);
106*387f9dfdSAndroid Build Coastguard Worker 
107*387f9dfdSAndroid Build Coastguard Worker   return 0;
108*387f9dfdSAndroid Build Coastguard Worker }
109