Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation version 2 only.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- Note: This program has not been tested beyond it's first use, so it's bound to be full of bugs.
- */
- /* This is a tool to get a stack trace of another program during a performance hit.
- This probably only work on linux (possibly mac). you will need to install pstack and pidof.
- To Use:
- Don't forget to set a sensible value for max_pet_delay.
- compile with: g++ pet.cpp -o pet -pthread -std=c++11 -Wl,--no-as-needed
- your_prog should simply printf("\nadopt\n") or cout<<"\nadopt\n" when you want to begin the timer.
- every frame thereafter, print/cout "\npet\n"
- call with: ./your_prog 2>&1 | ./pet your_prog
- */
- #include <ctime>
- #include <iostream>
- #include <string>
- #include <thread>
- #include <cassert>
- double GetTime( void );
- inline double GetTime( void ) {
- return static_cast< double >( std::clock() ) / CLOCKS_PER_SEC;
- }
- class NeedyPet {
- public:
- NeedyPet( void ) = delete;
- explicit NeedyPet( const int prog_pid );
- public:
- void MainLoop( void );
- private:
- void GetMessage( void );
- bool CheckPet( void );
- void CheckMessage( void );
- private:
- std::string message;
- double start;
- double last_pet;
- int pid;
- const double max_pet_delay;
- bool response_from_master=false;
- bool adopted = false;
- };
- NeedyPet::NeedyPet( const int prog_pid )
- : message()
- , start(0)
- , last_pet(0)
- , pid( prog_pid)
- , max_pet_delay(0.2f) // game runs at 60fps, so this is just fine
- , response_from_master(false)
- , adopted(false)
- {
- std::cout << R"(Waiting for input to be piped in. Send "adopt" (witout quotes) to begin, and "pet" every frame to sync.)" << "\n";
- }
- void NeedyPet::GetMessage( void ) {
- getline(std::cin, message);
- response_from_master = true;
- }
- bool NeedyPet::CheckPet( void ) {
- if ( ! adopted )
- return false;
- const double now( GetTime() );
- const double time_since_last_pet( now - last_pet );
- if ( time_since_last_pet > max_pet_delay ) {
- last_pet = now;
- std::string cmd("pstack ");
- char c[13];
- snprintf( c, 13, "%i", pid );
- cmd.append( c );
- std::cout << start << ": " << R"(DOING A STACK TRACE with: `)" << cmd << "`\n";
- system(cmd.c_str());
- return true;
- }
- return false;
- }
- void NeedyPet::CheckMessage( void ) {
- if ( message == "adopt" ) {
- if ( adopted )
- return;
- last_pet = start = GetTime();
- std::cout << start << ": " << message << "\n";
- adopted = true;
- std::cout << R"(process has been adopted)" << "\n";
- return;
- }
- if ( ! adopted )
- return;
- if ( message == "pet" ) {
- last_pet = GetTime();
- std::cout << last_pet << ": " << message << "\n";
- return;
- }
- if ( message.size() > 0 )
- std::cout << message << "\n";
- }
- void NeedyPet::MainLoop( void ) {
- std::shared_ptr< std::thread > thread;
- while ( true ) {
- if ( !thread )
- thread = std::make_shared<std::thread>( &NeedyPet::GetMessage, this );
- if ( response_from_master ) {
- assert( thread );
- thread->join();
- thread.reset();
- response_from_master = false;
- CheckMessage();
- }
- if ( CheckPet() )
- break;
- }
- if ( thread->joinable() )
- thread->join();
- }
- int main ( int argv, char** argc ) {
- if ( argv < 2 ) {
- std::cout << "please specify the name of the application\n";
- return -1;
- }
- std::cout << "Getting PID of `" << argc[1] << "`\n";
- std::string cmd("pidof ");
- cmd += argc[1];
- FILE *pipe = popen(cmd.c_str(), "r");
- if ( !pipe ) {
- std::cout << "Coudln't open pipe to 'pidof'\n";
- exit(1);
- }
- char c[13];
- int pid;
- if ( ! fgets(c, 13, pipe) ) {
- std::cout << "Couldn't get pipe's return.\n";
- pclose(pipe);
- exit(-1);
- }
- pid = atoi(c);
- std::cout << "Got PID: " << pid << "\n";
- NeedyPet myPet( pid );
- myPet.MainLoop();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement