summaryrefslogblamecommitdiffstatshomepage
path: root/src/emu/profiler.cpp
blob: 57b775556b20fb9220dd23c0b69a94c8db79831b (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                                





                                                                            

                                                                            

                                                                      
 




                                             

                                                            


                                                                            
                


                     
 


                                                                            
 
                     
 
                         
                           

  

 


                                                                            
 
                          
 
 
 
                                                                            


                                                                            
                                   



                                                                            

                                                                            
 


                                                   
 














                                                                            


                                          
                     


 
 
                                                   
                             

                                                   
                                             
 
                                      
 



                                    
 




                                                 
         
                                                   
                                    
         
 
 
 
 
                                                   
                                                    
                                                   
 
                                                               
 
                                 
 

                                                           
 




                                                                                                               
         

               
                              

 
 
 
                                                   
                                                
                                                   
 
                                                               
 
                                             
         
                                                                 
                                                                  


















                                                                      



                                                        

                                                          
          
 


                                                                              
                                                                                     
                                            
 

                                                                      
                                                    
                                            
 

                                                                                                          
                       
                                         
         
                       
         
 
                                                      
                                                    
                                                                                  
         
                                                               
                                           
 
                                                                             
                                  
                 
                                                                  
                                                                                                             
 
                                                                                                     
                                                        
                                                                                                                             
 
                                            
                                                                                               
                                                                                                                           
                            

                                                                 
                                         
                                                                           

                                                      
 
                                                        
                                            


                 

                                          
 
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    profiler.c

    Functions to manage profiling of MAME execution.

****************************************************************************

    Profiling is scope-based. To start profiling, put a profiler_scope
    object on the stack. To end profiling, just end the scope:

    {
        profiler_scope scope(PROFILER_VIDEO);

        your_work_here();
    }

    the profiler handles a FILO list so calls may be nested.

***************************************************************************/

#include "emu.h"
#include "profiler.h"



//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

struct profile_string
{
	int         type;
	const char *string;
};



//**************************************************************************
//  GLOBAL VARIABLES
//**************************************************************************

profiler_state g_profiler;



//**************************************************************************
//  CONSTANTS
//**************************************************************************

#define TEXT_UPDATE_TIME        0.5



//**************************************************************************
//  DUMMY PROFILER STATE
//**************************************************************************

//-------------------------------------------------
//  dummy_profiler_state - constructor
//-------------------------------------------------

dummy_profiler_state::dummy_profiler_state()
{
}



//**************************************************************************
//  REAL PROFILER STATE
//**************************************************************************

//-------------------------------------------------
//  real_profiler_state - constructor
//-------------------------------------------------

real_profiler_state::real_profiler_state()
{
	memset(m_filo, 0, sizeof(m_filo));
	memset(m_data, 0, sizeof(m_data));
	reset(false);
}



//-------------------------------------------------
//  reset - initializes state
//-------------------------------------------------

void real_profiler_state::reset(bool enabled)
{
	m_text_time = attotime::never;

	if (enabled)
	{
		// we're enabled now
		m_filoptr = m_filo;

		// set up dummy entry
		m_filoptr->start = 0;
		m_filoptr->type = PROFILER_TOTAL;
	}
	else
	{
		// magic value to indicate disabled
		m_filoptr = nullptr;
	}
}



//-------------------------------------------------
//  text - return the current text in an std::string
//-------------------------------------------------

const char *real_profiler_state::text(running_machine &machine)
{
	start(PROFILER_PROFILER);

	// get the current time
	attotime current_time = machine.scheduler().time();

	// we only want to update the text periodically
	if ((m_text_time == attotime::never) || ((current_time - m_text_time).as_double() >= TEXT_UPDATE_TIME))
	{
		update_text(machine);
		m_text_time = current_time;
	}

	stop();
	return m_text.c_str();
}



//-------------------------------------------------
//  update_text - update the current std::string
//-------------------------------------------------

void real_profiler_state::update_text(running_machine &machine)
{
	static const profile_string names[] =
	{
		{ PROFILER_DRC_COMPILE,      "DRC Compilation" },
		{ PROFILER_MEM_REMAP,        "Memory Remapping" },
		{ PROFILER_MEMREAD,          "Memory Read" },
		{ PROFILER_MEMWRITE,         "Memory Write" },
		{ PROFILER_VIDEO,            "Video Update" },
		{ PROFILER_DRAWGFX,          "drawgfx" },
		{ PROFILER_COPYBITMAP,       "copybitmap" },
		{ PROFILER_TILEMAP_DRAW,     "Tilemap Draw" },
		{ PROFILER_TILEMAP_DRAW_ROZ, "Tilemap ROZ Draw" },
		{ PROFILER_TILEMAP_UPDATE,   "Tilemap Update" },
		{ PROFILER_BLIT,             "OSD Blitting" },
		{ PROFILER_SOUND,            "Sound Generation" },
		{ PROFILER_TIMER_CALLBACK,   "Timer Callbacks" },
		{ PROFILER_INPUT,            "Input Processing" },
		{ PROFILER_MOVIE_REC,        "Movie Recording" },
		{ PROFILER_LOGERROR,         "Error Logging" },
		{ PROFILER_EXTRA,            "Unaccounted/Overhead" },
		{ PROFILER_USER1,            "User 1" },
		{ PROFILER_USER2,            "User 2" },
		{ PROFILER_USER3,            "User 3" },
		{ PROFILER_USER4,            "User 4" },
		{ PROFILER_USER5,            "User 5" },
		{ PROFILER_USER6,            "User 6" },
		{ PROFILER_USER7,            "User 7" },
		{ PROFILER_USER8,            "User 8" },
		{ PROFILER_PROFILER,         "Profiler" },
		{ PROFILER_IDLE,             "Idle" }
	};

	// compute the total time for all bits, not including profiler or idle
	UINT64 computed = 0;
	profile_type curtype;
	for (curtype = PROFILER_DEVICE_FIRST; curtype < PROFILER_PROFILER; ++curtype)
		computed += m_data[curtype];

	// save that result in normalize, and continue adding the rest
	UINT64 normalize = computed;
	for ( ; curtype < PROFILER_TOTAL; ++curtype)
		computed += m_data[curtype];

	// this becomes the total; if we end up with 0 for anything, we were just started, so return empty
	UINT64 total = computed;
	m_text.clear();
	if (total == 0 || normalize == 0)
	{
		return;
	}

	// loop over all types and generate the string
	device_iterator iter(machine.root_device());
	for (curtype = PROFILER_DEVICE_FIRST; curtype < PROFILER_TOTAL; ++curtype)
	{
		// determine the accumulated time for this type
		computed = m_data[curtype];

		// if we have non-zero data and we're ready to display, do it
		if (computed != 0)
		{
			// start with the un-normalized percentage
			m_text.append(string_format("%02d%% ", (int)((computed * 100 + total / 2) / total)));

			// followed by the normalized percentage for everything but profiler and idle
			if (curtype < PROFILER_PROFILER)
				m_text.append(string_format("%02d%% ", (int)((computed * 100 + normalize / 2) / normalize)));

			// and then the text
			if (curtype >= PROFILER_DEVICE_FIRST && curtype <= PROFILER_DEVICE_MAX)
				m_text.append(string_format("'%s'", iter.byindex(curtype - PROFILER_DEVICE_FIRST)->tag()));
			else
				for (auto & name : names)
					if (name.type == curtype)
					{
						m_text.append(name.string);
						break;
					}

			// followed by a carriage return
			m_text.append("\n");
		}
	}

	// reset data set to 0
	memset(m_data, 0, sizeof(m_data));
}