diff options
author | Darkvater <darkvater@openttd.org> | 2006-03-26 21:15:09 +0000 |
---|---|---|
committer | Darkvater <darkvater@openttd.org> | 2006-03-26 21:15:09 +0000 |
commit | a91c52e16909976b40951cf2893f2349e9ebf25d (patch) | |
tree | 07ce18ba583aad9caf062c352c2632ba1ea394c6 | |
parent | 4125aa21f8dfc72a60bf70b890b95c2187425112 (diff) | |
download | openttd-a91c52e16909976b40951cf2893f2349e9ebf25d.tar.xz |
(svn r4125) - Feature: Add a general TIC() TOC() mechanism using rdtsc or something similar on non-i386 architectures to performance-tune (critical) code. Some systems are probably missing, but those can be added later.
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | debug.h | 23 | ||||
-rw-r--r-- | functions.h | 6 | ||||
-rw-r--r-- | openttd.dsp | 6 | ||||
-rw-r--r-- | openttd.vcproj | 3 | ||||
-rw-r--r-- | os_timer.c | 69 | ||||
-rw-r--r-- | train_cmd.c | 30 | ||||
-rw-r--r-- | win32.c | 19 |
8 files changed, 106 insertions, 51 deletions
@@ -670,6 +670,7 @@ SRCS += oldloader.c SRCS += openttd.c SRCS += order_cmd.c SRCS += order_gui.c +SRCS += os_timer.c SRCS += pathfind.c SRCS += player_gui.c SRCS += players.c @@ -26,4 +26,27 @@ void CDECL debug(const char *s, ...); void SetDebugString(const char *s); const char *GetDebugString(void); +/* MSVC of course has to have a different syntax for long long *sigh* */ +#ifdef _MSC_VER +# define OTTD_PRINTF64 "I64" +#else +# define OTTD_PRINTF64 "ll" +#endif + +// Used for profiling +#define TIC() {\ + extern uint64 _rdtsc(void);\ + uint64 _xxx_ = _rdtsc();\ + static uint64 __sum__ = 0;\ + static uint32 __i__ = 0; + +#define TOC(str, count)\ + __sum__ += _rdtsc() - _xxx_;\ + if (++__i__ == count) {\ + printf("[%s]: %" OTTD_PRINTF64 "u [avg: %.1f]\n", str, __sum__, __sum__/(double)__i__);\ + __i__ = 0;\ + __sum__ = 0;\ + }\ +} + #endif /* DEBUG_H */ diff --git a/functions.h b/functions.h index cf558f3ae..18fd82d5e 100644 --- a/functions.h +++ b/functions.h @@ -116,12 +116,6 @@ static inline TileIndex RandomTile(void) { return TILE_MASK(Random()); } uint32 InteractiveRandom(void); /* Used for random sequences that are not the same on the other end of the multiplayer link */ uint InteractiveRandomRange(uint max); - -// Used for profiling -#define TIC() { extern uint32 _rdtsc(void); uint32 _xxx_ = _rdtsc(); static float __avg__; -#define TOC(s) _xxx_ = _rdtsc() - _xxx_; __avg__=__avg__*0.99+_xxx_*0.01; printf("%s: %8d %f\n", s, _xxx_,__avg__); } - - void SetDate(uint date); /* facedraw.c */ void DrawPlayerFace(uint32 face, int color, int x, int y); diff --git a/openttd.dsp b/openttd.dsp index 550d7c661..b8e28ed7f 100644 --- a/openttd.dsp +++ b/openttd.dsp @@ -339,6 +339,12 @@ SOURCE=.\ottdres.rc # End Source File # Begin Source File +SOURCE=.\os_timer.c +# End Source File +# Begin Source File + +# Begin Source File + SOURCE=.\pathfind.c # End Source File # Begin Source File diff --git a/openttd.vcproj b/openttd.vcproj index 1f9028ee4..1fa63899d 100644 --- a/openttd.vcproj +++ b/openttd.vcproj @@ -299,6 +299,9 @@ RelativePath=".\ottdres.rc"> </File> <File + RelativePath=".\os_timer.c"> + </File> + <File RelativePath=".\pathfind.c"> </File> <File diff --git a/os_timer.c b/os_timer.c new file mode 100644 index 000000000..89c25d010 --- /dev/null +++ b/os_timer.c @@ -0,0 +1,69 @@ +#include "stdafx.h"
+
+#undef RDTSC_AVAILABLE
+
+/* rdtsc for MSC_VER, uses simple inline assembly, or _rdtsc
+ * from external win64.asm because VS2005 does not support inline assembly */
+#if defined(_MSC_VER) && !defined(RDTSC_AVAILABLE)
+# if defined (_M_AMD64)
+extern uint64 _rdtsc(void);
+# else
+uint64 _declspec(naked) _rdtsc(void)
+{
+ _asm {
+ rdtsc
+ ret
+ }
+}
+# endif
+# define RDTSC_AVAILABLE
+#endif
+
+/* rdtsc for OS/2. Hopefully this works, who knows */
+#if defined (__WATCOMC__) && !defined(RDTSC_AVAILABLE)
+unsigned __int64 _rdtsc( void);
+# pragma aux _rdtsc = 0x0F 0x31 value [edx eax] parm nomemory modify exact [edx eax] nomemory;
+# define RDTSC_AVAILABLE
+#endif
+
+/* rdtsc for all other *nix-en (hopefully). Use GCC syntax */
+#if defined(__i386__) || defined(__x86_64__) && !defined(RDTSC_AVAILABLE)
+uint64 _rdtsc(void)
+{
+ uint32 high, low;
+ __asm__ __volatile__ ("rdtsc" : "=a" (low), "=d" (high));
+ return ((uint64)high << 32) | low;
+}
+# define RDTSC_AVAILABLE
+#endif
+
+/* rdtsc for PPC which has this not */
+#if defined(__POWERPC__) && !defined(RDTSC_AVAILABLE)
+uint64 _rdtsc(void)
+{
+ uint32 high, low;
+ uint32 high2 = 0;
+ /* PPC does not have rdtsc, so we cheat by reading the two 32-bit time-counters
+ * it has, 'Move From Time Base (Upper)'. Since these are two reads, in the
+ * very unlikely event that the lower part overflows to the upper part while we
+ * read it; we double-check and reread the registers */
+ asm volatile (
+ "mftbu %0\n"
+ "mftb %1\n"
+ "mftbu %2\n"
+ "cmpw %3,%4\n"
+ "bne- $-16\n"
+ : "=r" (high), "=r" (low), "=r" (high2)
+ : "0" (high), "2" (high2)
+ );
+ return ((uint64)high << 32) | low;
+}
+# define RDTSC_AVAILABLE
+#endif
+
+/* In all other cases we have no support for rdtsc. No major issue,
+ * you just won't be able to profile your code with TIC()/TOC() */
+#if !defined(RDTSC_AVAILABLE)
+#warning "OS has no support for rdtsc()"
+uint64 _rdtsc(void) {return 0;}
+#endif
diff --git a/train_cmd.c b/train_cmd.c index 245f37e3e..e5fd26772 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -2087,29 +2087,6 @@ static const byte _search_directions[6][4] = { }; static const byte _pick_track_table[6] = {1, 3, 2, 2, 0, 0}; -#ifdef PF_BENCHMARK -#if !defined(_MSC_VER) -unsigned int _rdtsc() -{ - unsigned int high, low; - - __asm__ __volatile__ ("rdtsc" : "=a" (low), "=d" (high)); - return low; -} -#else -#ifndef _M_AMD64 -static unsigned int _declspec(naked) _rdtsc(void) -{ - _asm { - rdtsc - ret - } -} -#endif -#endif -#endif - - /* choose a track */ static byte ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, TrackdirBits trackdirbits) @@ -2117,8 +2094,7 @@ static byte ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, TrainTrackFollowerData fd; uint best_track; #ifdef PF_BENCHMARK - int time = _rdtsc(); - static float f; + TIC() #endif assert((trackdirbits & ~0x3F) == 0); @@ -2171,9 +2147,7 @@ static byte ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, } #ifdef PF_BENCHMARK - time = _rdtsc() - time; - f = f * 0.99 + 0.01 * time; - printf("PF time = %d %f\n", time, f); + TOC("PF time = ", 1) #endif return best_track; @@ -62,11 +62,6 @@ bool LoadLibraryList(Function proc[], const char* dll) } #ifdef _MSC_VER -# ifdef _M_AMD64 -void* _get_save_esp(void); -uint64 _rdtsc(void); -# endif - static const char *_exception_string; #endif @@ -594,6 +589,7 @@ static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep) static void Win32InitializeExceptions(void) { #ifdef _M_AMD64 + extern void *_get_save_esp(void); _safe_esp = _get_save_esp(); #else _asm { @@ -603,7 +599,7 @@ static void Win32InitializeExceptions(void) SetUnhandledExceptionFilter(ExceptionHandler); } -#endif +#endif /* _MSC_VER */ static char *_fios_path; static char *_fios_save_path; @@ -1057,17 +1053,6 @@ static int ParseCommandLine(char *line, char **argv, int max_argc) return n; } - -#if defined(_MSC_VER) && !defined(_M_AMD64) -uint64 _declspec(naked) _rdtsc(void) -{ - _asm { - rdtsc - ret - } -} -#endif - void CreateConsole(void) { HANDLE hand; |