// license:BSD-3-Clause // copyright-holders:Aaron Giles /*************************************************************************** profiler.h 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. ***************************************************************************/ #pragma once #ifndef __PROFILER_H__ #define __PROFILER_H__ #include "attotime.h" //************************************************************************** // CONSTANTS //************************************************************************** enum profile_type { PROFILER_DEVICE_FIRST = 0, PROFILER_DEVICE_MAX = PROFILER_DEVICE_FIRST + 256, PROFILER_DRC_COMPILE, PROFILER_MEM_REMAP, PROFILER_MEMREAD, PROFILER_MEMWRITE, PROFILER_VIDEO, PROFILER_DRAWGFX, PROFILER_COPYBITMAP, PROFILER_TILEMAP_DRAW, PROFILER_TILEMAP_DRAW_ROZ, PROFILER_TILEMAP_UPDATE, PROFILER_BLIT, PROFILER_SOUND, PROFILER_TIMER_CALLBACK, PROFILER_INPUT, // input.c and inptport.c PROFILER_MOVIE_REC, // movie recording PROFILER_LOGERROR, // logerror PROFILER_EXTRA, // everything else // the USER types are available to driver writers to profile // custom sections of the code PROFILER_USER1, PROFILER_USER2, PROFILER_USER3, PROFILER_USER4, PROFILER_USER5, PROFILER_USER6, PROFILER_USER7, PROFILER_USER8, PROFILER_PROFILER, PROFILER_IDLE, PROFILER_TOTAL }; DECLARE_ENUM_OPERATORS(profile_type) //************************************************************************** // TYPE DEFINITIONS //************************************************************************** // ======================> real_profiler_state class real_profiler_state { public: // construction/destruction real_profiler_state(); // getters bool enabled() const { return m_filoptr != nullptr; } const char *text(running_machine &machine); // enable/disable void enable(bool state = true) { if (state != enabled()) { reset(state); } } // start/stop void start(profile_type type) { if (enabled()) real_start(type); } void stop() { if (enabled()) real_stop(); } private: void reset(bool enabled); void update_text(running_machine &machine); //------------------------------------------------- // real_start - mark the beginning of a // profiler entry //------------------------------------------------- ATTR_FORCE_INLINE void real_start(profile_type type) { // fail if we overflow if (m_filoptr >= &m_filo[ARRAY_LENGTH(m_filo) - 1]) throw emu_fatalerror("Profiler FILO overflow (type = %d)\n", type); // get current tick count osd_ticks_t curticks = get_profile_ticks(); // update previous entry m_data[m_filoptr->type] += curticks - m_filoptr->start; // move to next entry m_filoptr++; // fill in this entry m_filoptr->type = type; m_filoptr->start = curticks; } //------------------------------------------------- // real_stop - mark the end of a profiler entry //------------------------------------------------- ATTR_FORCE_INLINE void real_stop() { // degenerate scenario if (UNEXPECTED(m_filoptr <= m_filo)) return; // get current tick count osd_ticks_t curticks = get_profile_ticks(); // account for the time taken m_data[m_filoptr->type] += curticks - m_filoptr->start; // move back an entry m_filoptr--; // reset previous entry start time m_filoptr->start = curticks; } // an entry in the FILO struct filo_entry { int type; // type of entry osd_ticks_t start; // start time }; // internal state filo_entry * m_filoptr; // current FILO index std::string m_text; // profiler text attotime m_text_time; // profiler text last update filo_entry m_filo[32]; // array of FILO entries osd_ticks_t m_data[PROFILER_TOTAL + 1]; // array of data }; // ======================> dummy_profiler_state class dummy_profiler_state { public: // construction/destruction dummy_profiler_state(); // getters bool enabled() const { return false; } const char *text(running_machine &machine) { return ""; } // enable/disable void enable(bool state = true) { } // start/stop void start(profile_type type) { } void stop() { } }; // ======================> profiler_state #ifdef MAME_PROFILER typedef real_profiler_state profiler_state; #else typedef dummy_profiler_state profiler_state; #endif //************************************************************************** // GLOBAL VARIABLES //************************************************************************** extern profiler_state g_profiler; #endif /* __PROFILER_H__ */