From 5ff8efa9e5947664c2b6a5a195e375362818e05e Mon Sep 17 00:00:00 2001 From: notaz Date: Thu, 31 Dec 2009 15:51:40 +0000 Subject: [PATCH] simple profiler added git-svn-id: file:///home/notaz/opt/svn/PicoDrive/platform@850 be3aeb3a-fb24-0410-a615-afba39da0efa --- common/common.mak | 4 ++ common/emu.c | 10 +++- linux/Makefile | 3 ++ linux/pprof.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++ linux/pprof.h | 54 ++++++++++++++++++++ 5 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 linux/pprof.c create mode 100644 linux/pprof.h diff --git a/common/common.mak b/common/common.mak index f9958f4..3ddf3fb 100644 --- a/common/common.mak +++ b/common/common.mak @@ -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 diff --git a/common/emu.c b/common/emu.c index bde10e4..f86526c 100644 --- a/common/emu.c +++ b/common/emu.c @@ -1347,6 +1347,8 @@ void emu_init(void) mkdir_path(path, pos, "srm"); mkdir_path(path, pos, "brm"); + pprof_init(); + make_config_cfg(path); config_readlrom(path); @@ -1373,6 +1375,8 @@ void emu_finish(void) #endif } + pprof_finish(); + PicoExit(); } @@ -1432,6 +1436,8 @@ void emu_loop(void) unsigned int timestamp; int diff, diff_lim; + pprof_start(main); + timestamp = get_ticks(); if (reset_timing) { reset_timing = 0; @@ -1537,7 +1543,7 @@ void emu_loop(void) PicoFrame(); pemu_finalize_frame(fpsbuff, notice_msg); - //plat_video_flip(); + // plat_video_flip(); /* frame limiter */ if (!reset_timing && !(currentConfig.EmuOpt & (EOPT_NO_FRMLIMIT|EOPT_EXT_FRMLIMIT))) @@ -1560,6 +1566,8 @@ void emu_loop(void) plat_video_flip(); pframes_done++; frames_done++; frames_shown++; + + pprof_end(main); } emu_set_fastforward(0); diff --git a/linux/Makefile b/linux/Makefile index 47a8dcc..3362a73 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -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 index 0000000..e1ecd1f --- /dev/null +++ b/linux/pprof.c @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include +#include + +#include + +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 index 0000000..88a97e3 --- /dev/null +++ b/linux/pprof.h @@ -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__ -- 2.39.5