summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarkvater <darkvater@openttd.org>2006-03-26 21:15:09 +0000
committerDarkvater <darkvater@openttd.org>2006-03-26 21:15:09 +0000
commita91c52e16909976b40951cf2893f2349e9ebf25d (patch)
tree07ce18ba583aad9caf062c352c2632ba1ea394c6
parent4125aa21f8dfc72a60bf70b890b95c2187425112 (diff)
downloadopenttd-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--Makefile1
-rw-r--r--debug.h23
-rw-r--r--functions.h6
-rw-r--r--openttd.dsp6
-rw-r--r--openttd.vcproj3
-rw-r--r--os_timer.c69
-rw-r--r--train_cmd.c30
-rw-r--r--win32.c19
8 files changed, 106 insertions, 51 deletions
diff --git a/Makefile b/Makefile
index c7b53f17e..d732b971c 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/debug.h b/debug.h
index 71d0dcbd1..9721fb882 100644
--- a/debug.h
+++ b/debug.h
@@ -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;
diff --git a/win32.c b/win32.c
index b95650cca..6987ffcf2 100644
--- a/win32.c
+++ b/win32.c
@@ -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;