(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.

This commit is contained in:
Darkvater 2006-03-26 21:15:09 +00:00
parent 4125aa21f8
commit a91c52e169
8 changed files with 106 additions and 51 deletions

View File

@ -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

23
debug.h
View File

@ -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 */

View File

@ -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);

View File

@ -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

View File

@ -298,6 +298,9 @@
<File
RelativePath=".\ottdres.rc">
</File>
<File
RelativePath=".\os_timer.c">
</File>
<File
RelativePath=".\pathfind.c">
</File>

69
os_timer.c Normal file
View File

@ -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

View File

@ -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;

19
win32.c
View File

@ -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;