109 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * PyPerf Profile Python Processes with Python stack-trace.
 | |
|  *        For Linux, uses BCC, eBPF. Embedded C.
 | |
|  *
 | |
|  * Example of using BPF to profile Python Processes with Python stack-trace.
 | |
|  *
 | |
|  * USAGE: PyPerf [-d|--duration DURATION_MS] [-c|--sample-rate SAMPLE_RATE]
 | |
|  *               [-v|--verbosity LOG_VERBOSITY]
 | |
|  *
 | |
|  * Copyright (c) Facebook, Inc.
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License")
 | |
|  */
 | |
| 
 | |
| #include <cinttypes>
 | |
| #include <cstdlib>
 | |
| #include <string>
 | |
| #include <vector>
 | |
| 
 | |
| #include "PyPerfDefaultPrinter.h"
 | |
| #include "PyPerfLoggingHelper.h"
 | |
| #include "PyPerfUtil.h"
 | |
| 
 | |
| int main(int argc, char** argv) {
 | |
|   // Argument parsing helpers
 | |
|   int pos = 1;
 | |
| 
 | |
|   auto parseIntArg = [&](std::vector<std::string> argNames, uint64_t& target) {
 | |
|     std::string arg(argv[pos]);
 | |
|     for (const auto& name : argNames) {
 | |
|       if (arg == name) {
 | |
|         if (pos == argc) {
 | |
|           std::fprintf(stderr, "Expect value after %s\n", arg.c_str());
 | |
|           std::exit(1);
 | |
|         }
 | |
|         pos++;
 | |
|         std::string value(argv[pos]);
 | |
|         try {
 | |
|           target = std::stoi(value);
 | |
|         } catch (const std::exception& e) {
 | |
|           std::fprintf(stderr, "Expect integer value after %s, got %s: %s\n",
 | |
|                        arg.c_str(), value.c_str(), e.what());
 | |
|           std::exit(1);
 | |
|         }
 | |
|         return true;
 | |
|       }
 | |
|     }
 | |
|     return false;
 | |
|   };
 | |
| 
 | |
|   auto parseBoolArg = [&](std::vector<std::string> argNames, bool& target) {
 | |
|     std::string arg(argv[pos]);
 | |
|     for (const auto& name : argNames) {
 | |
|       if (arg == ("--" + name)) {
 | |
|         target = true;
 | |
|         return true;
 | |
|       }
 | |
|       if (arg == "--no-" + name) {
 | |
|         target = false;
 | |
|         return true;
 | |
|       }
 | |
|     }
 | |
|     return false;
 | |
|   };
 | |
| 
 | |
|   // Default argument values
 | |
|   uint64_t sampleRate = 1000000;
 | |
|   uint64_t durationMs = 1000;
 | |
|   uint64_t verbosityLevel = 0;
 | |
|   bool showGILState = true;
 | |
|   bool showThreadState = true;
 | |
|   bool showPthreadIDState = false;
 | |
| 
 | |
|   while (true) {
 | |
|     if (pos >= argc) {
 | |
|       break;
 | |
|     }
 | |
|     bool found = false;
 | |
|     found = found || parseIntArg({"-c", "--sample-rate"}, sampleRate);
 | |
|     found = found || parseIntArg({"-d", "--duration"}, durationMs);
 | |
|     found = found || parseIntArg({"-v", "--verbose"}, verbosityLevel);
 | |
|     found = found || parseBoolArg({"show-gil-state"}, showGILState);
 | |
|     found = found || parseBoolArg({"show-thread-state"}, showThreadState);
 | |
|     found =
 | |
|         found || parseBoolArg({"show-pthread-id-state"}, showPthreadIDState);
 | |
|     if (!found) {
 | |
|       std::fprintf(stderr, "Unexpected argument: %s\n", argv[pos]);
 | |
|       std::exit(1);
 | |
|     }
 | |
|     pos++;
 | |
|   }
 | |
| 
 | |
|   ebpf::pyperf::setVerbosity(verbosityLevel);
 | |
|   ebpf::pyperf::logInfo(1, "Profiling Sample Rate: %" PRIu64 "\n", sampleRate);
 | |
|   ebpf::pyperf::logInfo(1, "Profiling Duration: %" PRIu64 "ms\n", durationMs);
 | |
|   ebpf::pyperf::logInfo(1, "Showing GIL state: %d\n", showGILState);
 | |
|   ebpf::pyperf::logInfo(1, "Showing Thread state: %d\n", showThreadState);
 | |
|   ebpf::pyperf::logInfo(1, "Showing Pthread ID state: %d\n",
 | |
|                         showPthreadIDState);
 | |
| 
 | |
|   ebpf::pyperf::PyPerfUtil util;
 | |
|   util.init();
 | |
| 
 | |
|   ebpf::pyperf::PyPerfDefaultPrinter printer(showGILState, showThreadState,
 | |
|                                              showPthreadIDState);
 | |
|   util.profile(sampleRate, durationMs, &printer);
 | |
| 
 | |
|   return 0;
 | |
| }
 |