xref: /aosp_15_r20/external/bcc/examples/cpp/pyperf/PyPerfDefaultPrinter.cc (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1 /*
2  * Copyright (c) Facebook, Inc.
3  * Licensed under the Apache License, Version 2.0 (the "License")
4  */
5 
6 #include <map>
7 #include <string>
8 
9 #include "PyPerfDefaultPrinter.h"
10 #include "PyPerfUtil.h"
11 
12 namespace ebpf {
13 namespace pyperf {
14 
15 const static std::string kLostSymbol = "[Lost Symbol]";
16 const static std::string kIncompleteStack = "[Truncated Stack]";
17 const static std::string kErrorStack = "[Stack Error]";
18 const static std::string kNonPythonStack = "[Non-Python Code]";
19 
20 const static std::map<int, const char*> kGILStateValues = {
21     {GIL_STATE_NO_INFO, "No GIL Info"},
22     {GIL_STATE_ERROR, "Error Reading GIL State"},
23     {GIL_STATE_UNINITIALIZED, "GIL Uninitialized"},
24     {GIL_STATE_NOT_LOCKED, "GIL Not Locked"},
25     {GIL_STATE_THIS_THREAD, "GIL on This Thread"},
26     {GIL_STATE_GLOBAL_CURRENT_THREAD,
27      "GIL on Global _PyThreadState_Current Thread"},
28     {GIL_STATE_OTHER_THREAD, "GIL on Unexpected Thread"},
29     {GIL_STATE_NULL, "GIL State Empty"}};
30 
31 const static std::map<int, const char*> kThreadStateValues = {
32     {THREAD_STATE_UNKNOWN, "ThreadState Unknown"},
33     {THREAD_STATE_MATCH, "TLS ThreadState is Global _PyThreadState_Current"},
34     {THREAD_STATE_MISMATCH,
35      "TLS ThreadState is not Global _PyThreadState_Current"},
36     {THREAD_STATE_THIS_THREAD_NULL, "TLS ThreadState is NULL"},
37     {THREAD_STATE_GLOBAL_CURRENT_THREAD_NULL,
38      "Global _PyThreadState_Current is NULL"},
39     {THREAD_STATE_BOTH_NULL,
40      "Both TLS ThreadState and Global _PyThreadState_Current is NULL"},
41 };
42 
43 const static std::map<int, const char*> kPthreadIDStateValues = {
44     {PTHREAD_ID_UNKNOWN, "Pthread ID Unknown"},
45     {PTHREAD_ID_MATCH, "System Pthread ID is Python ThreadState Pthread ID"},
46     {PTHREAD_ID_MISMATCH,
47      "System Pthread ID is not Python ThreadState Pthread ID"},
48     {PTHREAD_ID_THREAD_STATE_NULL, "No Pthread ID: TLS ThreadState is NULL"},
49     {PTHREAD_ID_NULL, "Pthread ID on TLS ThreadState is NULL"},
50     {PTHREAD_ID_ERROR, "Error Reading System Pthread ID"}};
51 
processSamples(const std::vector<PyPerfSample> & samples,PyPerfUtil * util)52 void PyPerfDefaultPrinter::processSamples(
53     const std::vector<PyPerfSample>& samples, PyPerfUtil* util) {
54   auto symbols = util->getSymbolMapping();
55   uint32_t lostSymbols = 0;
56   uint32_t truncatedStack = 0;
57 
58   for (auto& sample : samples) {
59     if (sample.threadStateMatch != THREAD_STATE_THIS_THREAD_NULL &&
60         sample.threadStateMatch != THREAD_STATE_BOTH_NULL) {
61       for (const auto stackId : sample.pyStackIds) {
62         auto symbIt = symbols.find(stackId);
63         if (symbIt != symbols.end()) {
64           std::printf("    %s\n", symbIt->second.c_str());
65         } else {
66           std::printf("    %s\n", kLostSymbol.c_str());
67           lostSymbols++;
68         }
69       }
70       switch (sample.stackStatus) {
71       case STACK_STATUS_TRUNCATED:
72         std::printf("    %s\n", kIncompleteStack.c_str());
73         truncatedStack++;
74         break;
75       case STACK_STATUS_ERROR:
76         std::printf("    %s\n", kErrorStack.c_str());
77         break;
78       default:
79         break;
80       }
81     } else {
82       std::printf("    %s\n", kNonPythonStack.c_str());
83     }
84 
85     std::printf("PID: %d TID: %d (%s)\n", sample.pid, sample.tid,
86                 sample.comm.c_str());
87     if (showGILState_)
88       std::printf("GIL State: %s\n", kGILStateValues.at(sample.gilState));
89     if (showThreadState_)
90       std::printf("Thread State: %s\n",
91                   kThreadStateValues.at(sample.threadStateMatch));
92     if (showPthreadIDState_)
93       std::printf("Pthread ID State: %s\n",
94                   kPthreadIDStateValues.at(sample.pthreadIDMatch));
95 
96     std::printf("\n");
97   }
98 
99   std::printf("%d samples collected\n", util->getTotalSamples());
100   std::printf("%d samples lost\n", util->getLostSamples());
101   std::printf("%d samples with truncated stack\n", truncatedStack);
102   std::printf("%d times Python symbol lost\n", lostSymbols);
103 }
104 
105 }  // namespace pyperf
106 }  // namespace ebpf
107