simple profiler added
authornotaz <notasas@gmail.com>
Thu, 31 Dec 2009 15:51:40 +0000 (15:51 +0000)
committernotaz <notasas@gmail.com>
Thu, 31 Dec 2009 15:51:40 +0000 (15:51 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive/platform@850 be3aeb3a-fb24-0410-a615-afba39da0efa

common/common.mak
common/emu.c
linux/Makefile
linux/pprof.c [new file with mode: 0644]
linux/pprof.h [new file with mode: 0644]

index f9958f4..3ddf3fb 100644 (file)
@@ -7,6 +7,10 @@ endif
 ifeq "$(profile)" "2"
 CFLAGS += -fprofile-use
 endif
+ifeq "$(pprof)" "1"
+DEFINES += PPROF
+OBJS += platform/linux/pprof.o
+endif
 
 # === Pico core ===
 # Pico
index bde10e4..f86526c 100644 (file)
@@ -1347,6 +1347,8 @@ void emu_init(void)
        mkdir_path(path, pos, "srm");\r
        mkdir_path(path, pos, "brm");\r
 \r
+       pprof_init();\r
+\r
        make_config_cfg(path);\r
        config_readlrom(path);\r
 \r
@@ -1373,6 +1375,8 @@ void emu_finish(void)
 #endif\r
        }\r
 \r
+       pprof_finish();\r
+\r
        PicoExit();\r
 }\r
 \r
@@ -1432,6 +1436,8 @@ void emu_loop(void)
                unsigned int timestamp;\r
                int diff, diff_lim;\r
 \r
+               pprof_start(main);\r
+\r
                timestamp = get_ticks();\r
                if (reset_timing) {\r
                        reset_timing = 0;\r
@@ -1537,7 +1543,7 @@ void emu_loop(void)
                PicoFrame();\r
                pemu_finalize_frame(fpsbuff, notice_msg);\r
 \r
-               //plat_video_flip();\r
+               // plat_video_flip();\r
 \r
                /* frame limiter */\r
                if (!reset_timing && !(currentConfig.EmuOpt & (EOPT_NO_FRMLIMIT|EOPT_EXT_FRMLIMIT)))\r
@@ -1560,6 +1566,8 @@ void emu_loop(void)
                plat_video_flip();\r
 \r
                pframes_done++; frames_done++; frames_shown++;\r
+\r
+               pprof_end(main);\r
        }\r
 \r
        emu_set_fastforward(0);\r
index 47a8dcc..3362a73 100644 (file)
@@ -88,6 +88,9 @@ PicoDrive : $(OBJS)
        @echo ">>>" $@
        $(CC) $(CFLAGS) $^ $(LDFLAGS) -Wl,-Map=PicoDrive.map -o $@
 
+pprof: pprof.c
+       $(CROSS)gcc -O2 -ggdb -DPPROF -DPPROF_TOOL -I../../ -I. $^ -o $@ -lrt
+
 %.o : %.asm
        @echo ">>>" $<
        nasm -f elf $< -o $@
diff --git a/linux/pprof.c b/linux/pprof.c
new file mode 100644 (file)
index 0000000..e1ecd1f
--- /dev/null
@@ -0,0 +1,126 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#include <pico/pico_int.h>
+
+struct pp_counters *pp_counters;
+static int shmemid;
+
+void pprof_init(void)
+{
+       int this_is_new_shmem = 1;
+       key_t shmemkey;
+       void *shmem;
+
+#ifndef PPROF_TOOL
+       unsigned int tmp = pprof_get_one();
+       printf("pprof: measured diff is %u\n", pprof_get_one() - tmp);
+#endif
+
+       shmemkey = ftok(".", 0x02ABC32E);
+       if (shmemkey == -1)
+       {
+               perror("pprof: ftok failed");
+               return;
+       }
+
+#ifndef PPROF_TOOL
+       shmemid = shmget(shmemkey, sizeof(*pp_counters),
+               IPC_CREAT | IPC_EXCL | 0644);
+       if (shmemid == -1)
+#endif
+       {
+               shmemid = shmget(shmemkey, sizeof(*pp_counters),
+                               0644);
+               if (shmemid == -1)
+               {
+                       perror("pprof: shmget failed");
+                       return;
+               }
+               this_is_new_shmem = 0;
+       }
+
+       shmem = shmat(shmemid, NULL, 0);
+       if (shmem == (void *)-1)
+       {
+               perror("pprof: shmat failed");
+               return;
+       }
+
+       pp_counters = shmem;
+       if (this_is_new_shmem) {
+               memset(pp_counters, 0, sizeof(*pp_counters));
+               printf("pprof: pp_counters cleared.\n");
+       }
+}
+
+void pprof_finish(void)
+{
+       shmdt(pp_counters);
+       shmctl(shmemid, IPC_RMID, NULL);
+}
+
+#ifdef PPROF_TOOL
+
+#define IT(n) { pp_##n, #n }
+static const struct {
+       enum pprof_points pp;
+       const char *name;
+} pp_tab[] = {
+       IT(main),
+       IT(frame),
+       IT(draw),
+       IT(sound),
+       IT(m68k),
+       IT(z80),
+       IT(msh2),
+       IT(ssh2),
+       IT(dummy),
+};
+
+int main(int argc, char *argv[])
+{
+       unsigned long long old[pp_total_points], new[pp_total_points];
+       int base = 0;
+       int l, i;
+
+       pprof_init();
+       if (pp_counters == NULL)
+               return 1;
+
+       if (argc >= 2)
+               base = atoi(argv[1]);
+
+       memset(old, 0, sizeof(old));
+       for (l = 0; ; l++)
+       {
+               if ((l & 0x1f) == 0) {
+                       for (i = 0; i < ARRAY_SIZE(pp_tab); i++)
+                               printf("%6s ", pp_tab[i].name);
+                       printf("\n");
+               }
+
+               memcpy(new, pp_counters->counter, sizeof(new));
+               for (i = 0; i < ARRAY_SIZE(pp_tab); i++)
+               {
+                       unsigned long long idiff = new[i] - old[i];
+                       unsigned long long bdiff = (new[base] - old[base]) | 1;
+                       printf("%6.2f ", (double)idiff * 100.0 / bdiff);
+               }
+               printf("\n");
+               memcpy(old, new, sizeof(old));
+
+               if (argc < 3)
+                       break;
+               usleep(atoi(argv[2]));
+       }
+
+       return 0;
+}
+
+#endif // PPROF_TOOL
+
diff --git a/linux/pprof.h b/linux/pprof.h
new file mode 100644 (file)
index 0000000..88a97e3
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef __PPROF_H__
+#define __PPROF_H__
+
+enum pprof_points {
+  pp_main,
+  pp_frame,
+  pp_draw,
+  pp_sound,
+  pp_m68k,
+  pp_z80,
+  pp_msh2,
+  pp_ssh2,
+  pp_dummy,
+  pp_total_points
+};
+
+struct pp_counters
+{
+       unsigned long long counter[pp_total_points];
+};
+
+extern struct pp_counters *pp_counters;
+
+#ifdef __i386__
+static __attribute__((always_inline)) inline unsigned int pprof_get_one(void)
+{
+  unsigned long long ret;
+  __asm__ __volatile__ ("rdtsc" : "=A" (ret));
+  return (unsigned int)ret;
+}
+
+#elif defined(__GP2X__)
+// XXX: MMSP2 only
+extern volatile unsigned long *gp2x_memregl;
+#define pprof_get_one() (unsigned int)gp2x_memregl[0x0a00 >> 2]
+
+#else
+#error no timer
+#endif
+
+#define pprof_start(point) { \
+    unsigned int pp_start_##point = pprof_get_one()
+#define pprof_end(point) \
+    pp_counters->counter[pp_##point] += pprof_get_one() - pp_start_##point; \
+  }
+// subtract for recursive stuff
+#define pprof_end_sub(point) \
+    pp_counters->counter[pp_##point] -= pprof_get_one() - pp_start_##point; \
+  }
+
+extern void pprof_init(void);
+extern void pprof_finish(void);
+
+#endif // __PPROF_H__