Advertisement
Guest User

Tool to call stack trace during performance hit

a guest
Apr 23rd, 2014
179
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.36 KB | None | 0 0
  1. /*
  2.     This program is free software: you can redistribute it and/or modify
  3.     it under the terms of the GNU General Public License as published by
  4.     the Free Software Foundation version 2 only.
  5.  
  6.     This program is distributed in the hope that it will be useful,
  7.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.     GNU General Public License for more details.
  10.  
  11.     You should have received a copy of the GNU General Public License
  12.     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  13.      
  14.     Note: This program has not been tested beyond it's first use, so it's bound to be full of bugs.
  15. */
  16.  
  17. /*  This is a tool to get a stack trace of another program during a performance hit.
  18.     This probably only work on linux (possibly mac). you will need to install pstack and pidof.
  19.  
  20.     To Use:
  21.    
  22.     Don't forget to set a sensible value for max_pet_delay.
  23.  
  24.     compile with: g++ pet.cpp -o pet -pthread -std=c++11 -Wl,--no-as-needed
  25.  
  26.     your_prog should simply printf("\nadopt\n") or cout<<"\nadopt\n" when you want to begin the timer.
  27.  
  28.     every frame thereafter, print/cout "\npet\n"
  29.  
  30.     call with: ./your_prog 2>&1 | ./pet your_prog
  31. */
  32.  
  33. #include <ctime>
  34. #include <iostream>
  35. #include <string>
  36. #include <thread>
  37. #include <cassert>
  38.  
  39. double GetTime( void );
  40. inline double GetTime( void ) {
  41.     return static_cast< double >( std::clock() ) / CLOCKS_PER_SEC;
  42. }
  43.  
  44. class NeedyPet {
  45. public:
  46.     NeedyPet( void ) = delete;
  47.     explicit NeedyPet( const int prog_pid );
  48.    
  49. public:
  50.     void MainLoop( void );
  51.    
  52. private:
  53.     void GetMessage( void );
  54.     bool CheckPet( void );
  55.     void CheckMessage( void );
  56.  
  57. private:
  58.     std::string message;
  59.     double start;
  60.     double last_pet;
  61.     int pid;
  62.     const double max_pet_delay;
  63.     bool response_from_master=false;
  64.     bool adopted = false;
  65. };
  66.  
  67. NeedyPet::NeedyPet( const int prog_pid )   
  68.     : message()
  69.     , start(0)
  70.     , last_pet(0)
  71.     , pid( prog_pid)
  72.     , max_pet_delay(0.2f) // game runs at 60fps, so this is just fine
  73.     , response_from_master(false)
  74.     , adopted(false)
  75. {
  76.     std::cout << R"(Waiting for input to be piped in. Send "adopt" (witout quotes) to begin, and "pet" every frame to sync.)" << "\n";
  77. }  
  78.  
  79. void NeedyPet::GetMessage( void ) {
  80.     getline(std::cin, message);
  81.     response_from_master = true;
  82. }
  83.  
  84. bool NeedyPet::CheckPet( void ) {
  85.     if ( ! adopted )
  86.         return false;
  87.        
  88.     const double now( GetTime() );
  89.     const double time_since_last_pet( now - last_pet );
  90.    
  91.     if ( time_since_last_pet > max_pet_delay ) {
  92.         last_pet = now;
  93.        
  94.         std::string cmd("pstack ");
  95.         char c[13];
  96.         snprintf( c, 13, "%i", pid );
  97.         cmd.append( c );       
  98.        
  99.         std::cout << start << ": " << R"(DOING A STACK TRACE with: `)" << cmd << "`\n";
  100.         system(cmd.c_str());
  101.        
  102.         return true;
  103.     }  
  104.    
  105.     return false;
  106. }
  107.        
  108. void NeedyPet::CheckMessage( void ) {
  109.     if ( message == "adopt" ) {
  110.         if ( adopted )
  111.             return;
  112.        
  113.         last_pet = start = GetTime();
  114.         std::cout << start << ": " << message << "\n";
  115.         adopted = true;
  116.         std::cout << R"(process has been adopted)" << "\n";
  117.         return;
  118.     }
  119.    
  120.     if ( ! adopted )
  121.         return;
  122.        
  123.     if ( message == "pet" ) {
  124.         last_pet = GetTime();
  125.         std::cout << last_pet << ": " << message << "\n";
  126.         return;
  127.     }
  128.    
  129.     if ( message.size() > 0 )
  130.         std::cout << message << "\n";
  131. }
  132.    
  133. void NeedyPet::MainLoop( void ) {
  134.     std::shared_ptr< std::thread > thread;
  135.    
  136.     while ( true ) {
  137.         if ( !thread )
  138.              thread = std::make_shared<std::thread>( &NeedyPet::GetMessage, this );
  139.        
  140.         if ( response_from_master ) {
  141.             assert( thread );
  142.             thread->join();
  143.             thread.reset();
  144.             response_from_master = false;
  145.             CheckMessage();
  146.         }
  147.  
  148.         if ( CheckPet() )
  149.             break;
  150.     }
  151.    
  152.     if ( thread->joinable() )
  153.         thread->join();
  154. }
  155.        
  156. int main ( int argv, char** argc ) {
  157.     if ( argv < 2 ) {
  158.         std::cout << "please specify the name of the application\n";
  159.         return -1;
  160.     }
  161.    
  162.     std::cout << "Getting PID of `" << argc[1] << "`\n";
  163.    
  164.     std::string cmd("pidof ");
  165.     cmd += argc[1];
  166.  
  167.     FILE *pipe = popen(cmd.c_str(), "r");
  168.     if ( !pipe ) {
  169.         std::cout << "Coudln't open pipe to 'pidof'\n";
  170.         exit(1);
  171.     }
  172.  
  173.     char c[13];
  174.     int pid;
  175.     if ( ! fgets(c, 13, pipe) ) {
  176.         std::cout << "Couldn't get pipe's return.\n";
  177.         pclose(pipe);
  178.         exit(-1);
  179.     }
  180.    
  181.     pid = atoi(c);
  182.    
  183.     std::cout << "Got PID: " << pid << "\n";
  184.  
  185.     NeedyPet myPet( pid );
  186.     myPet.MainLoop();
  187.     return 0;
  188. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement