107 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			107 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * Copyright (c) Facebook, Inc.
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License")
 | |
|  */
 | |
| 
 | |
| #include <map>
 | |
| #include <string>
 | |
| 
 | |
| #include "PyPerfDefaultPrinter.h"
 | |
| #include "PyPerfUtil.h"
 | |
| 
 | |
| namespace ebpf {
 | |
| namespace pyperf {
 | |
| 
 | |
| const static std::string kLostSymbol = "[Lost Symbol]";
 | |
| const static std::string kIncompleteStack = "[Truncated Stack]";
 | |
| const static std::string kErrorStack = "[Stack Error]";
 | |
| const static std::string kNonPythonStack = "[Non-Python Code]";
 | |
| 
 | |
| const static std::map<int, const char*> kGILStateValues = {
 | |
|     {GIL_STATE_NO_INFO, "No GIL Info"},
 | |
|     {GIL_STATE_ERROR, "Error Reading GIL State"},
 | |
|     {GIL_STATE_UNINITIALIZED, "GIL Uninitialized"},
 | |
|     {GIL_STATE_NOT_LOCKED, "GIL Not Locked"},
 | |
|     {GIL_STATE_THIS_THREAD, "GIL on This Thread"},
 | |
|     {GIL_STATE_GLOBAL_CURRENT_THREAD,
 | |
|      "GIL on Global _PyThreadState_Current Thread"},
 | |
|     {GIL_STATE_OTHER_THREAD, "GIL on Unexpected Thread"},
 | |
|     {GIL_STATE_NULL, "GIL State Empty"}};
 | |
| 
 | |
| const static std::map<int, const char*> kThreadStateValues = {
 | |
|     {THREAD_STATE_UNKNOWN, "ThreadState Unknown"},
 | |
|     {THREAD_STATE_MATCH, "TLS ThreadState is Global _PyThreadState_Current"},
 | |
|     {THREAD_STATE_MISMATCH,
 | |
|      "TLS ThreadState is not Global _PyThreadState_Current"},
 | |
|     {THREAD_STATE_THIS_THREAD_NULL, "TLS ThreadState is NULL"},
 | |
|     {THREAD_STATE_GLOBAL_CURRENT_THREAD_NULL,
 | |
|      "Global _PyThreadState_Current is NULL"},
 | |
|     {THREAD_STATE_BOTH_NULL,
 | |
|      "Both TLS ThreadState and Global _PyThreadState_Current is NULL"},
 | |
| };
 | |
| 
 | |
| const static std::map<int, const char*> kPthreadIDStateValues = {
 | |
|     {PTHREAD_ID_UNKNOWN, "Pthread ID Unknown"},
 | |
|     {PTHREAD_ID_MATCH, "System Pthread ID is Python ThreadState Pthread ID"},
 | |
|     {PTHREAD_ID_MISMATCH,
 | |
|      "System Pthread ID is not Python ThreadState Pthread ID"},
 | |
|     {PTHREAD_ID_THREAD_STATE_NULL, "No Pthread ID: TLS ThreadState is NULL"},
 | |
|     {PTHREAD_ID_NULL, "Pthread ID on TLS ThreadState is NULL"},
 | |
|     {PTHREAD_ID_ERROR, "Error Reading System Pthread ID"}};
 | |
| 
 | |
| void PyPerfDefaultPrinter::processSamples(
 | |
|     const std::vector<PyPerfSample>& samples, PyPerfUtil* util) {
 | |
|   auto symbols = util->getSymbolMapping();
 | |
|   uint32_t lostSymbols = 0;
 | |
|   uint32_t truncatedStack = 0;
 | |
| 
 | |
|   for (auto& sample : samples) {
 | |
|     if (sample.threadStateMatch != THREAD_STATE_THIS_THREAD_NULL &&
 | |
|         sample.threadStateMatch != THREAD_STATE_BOTH_NULL) {
 | |
|       for (const auto stackId : sample.pyStackIds) {
 | |
|         auto symbIt = symbols.find(stackId);
 | |
|         if (symbIt != symbols.end()) {
 | |
|           std::printf("    %s\n", symbIt->second.c_str());
 | |
|         } else {
 | |
|           std::printf("    %s\n", kLostSymbol.c_str());
 | |
|           lostSymbols++;
 | |
|         }
 | |
|       }
 | |
|       switch (sample.stackStatus) {
 | |
|       case STACK_STATUS_TRUNCATED:
 | |
|         std::printf("    %s\n", kIncompleteStack.c_str());
 | |
|         truncatedStack++;
 | |
|         break;
 | |
|       case STACK_STATUS_ERROR:
 | |
|         std::printf("    %s\n", kErrorStack.c_str());
 | |
|         break;
 | |
|       default:
 | |
|         break;
 | |
|       }
 | |
|     } else {
 | |
|       std::printf("    %s\n", kNonPythonStack.c_str());
 | |
|     }
 | |
| 
 | |
|     std::printf("PID: %d TID: %d (%s)\n", sample.pid, sample.tid,
 | |
|                 sample.comm.c_str());
 | |
|     if (showGILState_)
 | |
|       std::printf("GIL State: %s\n", kGILStateValues.at(sample.gilState));
 | |
|     if (showThreadState_)
 | |
|       std::printf("Thread State: %s\n",
 | |
|                   kThreadStateValues.at(sample.threadStateMatch));
 | |
|     if (showPthreadIDState_)
 | |
|       std::printf("Pthread ID State: %s\n",
 | |
|                   kPthreadIDStateValues.at(sample.pthreadIDMatch));
 | |
| 
 | |
|     std::printf("\n");
 | |
|   }
 | |
| 
 | |
|   std::printf("%d samples collected\n", util->getTotalSamples());
 | |
|   std::printf("%d samples lost\n", util->getLostSamples());
 | |
|   std::printf("%d samples with truncated stack\n", truncatedStack);
 | |
|   std::printf("%d times Python symbol lost\n", lostSymbols);
 | |
| }
 | |
| 
 | |
| }  // namespace pyperf
 | |
| }  // namespace ebpf
 |