(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:
		
							
								
								
									
										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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Darkvater
					Darkvater