summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/profiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/profiler.c')
-rw-r--r--src/emu/profiler.c205
1 files changed, 205 insertions, 0 deletions
diff --git a/src/emu/profiler.c b/src/emu/profiler.c
new file mode 100644
index 00000000000..7c70ee4abc2
--- /dev/null
+++ b/src/emu/profiler.c
@@ -0,0 +1,205 @@
+/***************************************************************************
+
+ profiler.c
+
+ Functions to manage profiling of MAME execution.
+
+ Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "osdepend.h"
+#include "driver.h"
+#include "profiler.h"
+
+
+/* in usrintf.c */
+static int use_profiler;
+
+
+#define MEMORY 6
+
+typedef struct _profile_data profile_data;
+struct _profile_data
+{
+ UINT64 count[MEMORY][PROFILER_TOTAL];
+ unsigned int cpu_context_switches[MEMORY];
+};
+
+static profile_data profile;
+static int memory;
+
+
+static int FILO_type[10];
+static osd_ticks_t FILO_start[10];
+static int FILO_length;
+
+void profiler_start(void)
+{
+ use_profiler = 1;
+ FILO_length = 0;
+}
+
+void profiler_stop(void)
+{
+ use_profiler = 0;
+}
+
+void profiler_mark(int type)
+{
+ osd_ticks_t curr_ticks;
+
+
+ if (!use_profiler)
+ {
+ FILO_length = 0;
+ return;
+ }
+
+ if (type >= PROFILER_CPU1 && type <= PROFILER_CPU8)
+ profile.cpu_context_switches[memory]++;
+
+ curr_ticks = osd_profiling_ticks();
+
+ if (type != PROFILER_END)
+ {
+ if (FILO_length > 0)
+ {
+ if (FILO_length >= 10)
+ {
+logerror("Profiler error: FILO buffer overflow\n");
+ return;
+ }
+
+ /* handle nested calls */
+ profile.count[memory][FILO_type[FILO_length-1]] += curr_ticks - FILO_start[FILO_length-1];
+ }
+ FILO_type[FILO_length] = type;
+ FILO_start[FILO_length] = curr_ticks;
+ FILO_length++;
+ }
+ else
+ {
+ if (FILO_length <= 0)
+ {
+logerror("Profiler error: FILO buffer underflow\n");
+ return;
+ }
+
+ FILO_length--;
+ profile.count[memory][FILO_type[FILO_length]] += curr_ticks - FILO_start[FILO_length];
+ if (FILO_length > 0)
+ {
+ /* handle nested calls */
+ FILO_start[FILO_length-1] = curr_ticks;
+ }
+ }
+}
+
+const char *profiler_get_text(void)
+{
+ int i,j;
+ UINT64 total,normalize;
+ UINT64 computed;
+ static const char *names[PROFILER_TOTAL] =
+ {
+ "CPU 1 ",
+ "CPU 2 ",
+ "CPU 3 ",
+ "CPU 4 ",
+ "CPU 5 ",
+ "CPU 6 ",
+ "CPU 7 ",
+ "CPU 8 ",
+ "Mem rd ",
+ "Mem wr ",
+ "Video ",
+ "drawgfx",
+ "copybmp",
+ "tmdraw ",
+ "tmdrroz",
+ "tmupdat",
+ "Artwork",
+ "Blit ",
+ "Sound ",
+ "Mixer ",
+ "Callbck",
+ "Input ",
+ "Movie ",
+ "Logerr ",
+ "Extra ",
+ "User1 ",
+ "User2 ",
+ "User3 ",
+ "User4 ",
+ "Profilr",
+ "Idle ",
+ };
+ static int showdelay[PROFILER_TOTAL];
+ static char buf[50*40];
+ char *bufptr = buf;
+
+
+ if (!use_profiler) return "";
+
+ profiler_mark(PROFILER_PROFILER);
+
+ computed = 0;
+ i = 0;
+ while (i < PROFILER_PROFILER)
+ {
+ for (j = 0;j < MEMORY;j++)
+ computed += profile.count[j][i];
+ i++;
+ }
+ normalize = computed;
+ while (i < PROFILER_TOTAL)
+ {
+ for (j = 0;j < MEMORY;j++)
+ computed += profile.count[j][i];
+ i++;
+ }
+ total = computed;
+
+ if (total == 0 || normalize == 0) return ""; /* we have been just reset */
+
+ for (i = 0;i < PROFILER_TOTAL;i++)
+ {
+ computed = 0;
+ {
+ for (j = 0;j < MEMORY;j++)
+ computed += profile.count[j][i];
+ }
+ if (computed || showdelay[i])
+ {
+ if (computed) showdelay[i] = ATTOSECONDS_TO_HZ(Machine->screen[0].refresh);
+ showdelay[i]--;
+
+ if (i < PROFILER_PROFILER)
+ bufptr += sprintf(bufptr,"%02d%% %02d%% %s\n",
+ (int)((computed * 100 + total/2) / total),
+ (int)((computed * 100 + normalize/2) / normalize),
+ names[i]);
+ else
+ bufptr += sprintf(bufptr,"%02d%% %s\n",
+ (int)((computed * 100 + total/2) / total),
+ names[i]);
+ }
+ }
+
+ i = 0;
+ for (j = 0;j < MEMORY;j++)
+ i += profile.cpu_context_switches[j];
+ bufptr += sprintf(bufptr,"%4d CPU switches\n",i / MEMORY);
+
+ /* reset the counters */
+ memory = (memory + 1) % MEMORY;
+ profile.cpu_context_switches[memory] = 0;
+ for (i = 0;i < PROFILER_TOTAL;i++)
+ profile.count[memory][i] = 0;
+
+ profiler_mark(PROFILER_END);
+
+ return buf;
+}