mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-01-22 15:11:54 +00:00
(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:
parent
4125aa21f8
commit
a91c52e169
1
Makefile
1
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
|
||||
|
23
debug.h
23
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 */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
69
os_timer.c
Normal 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
|
30
train_cmd.c
30
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;
|
||||
|
19
win32.c
19
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;
|
||||
|
Loading…
Reference in New Issue
Block a user