(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 += openttd.c | ||||||
| SRCS += order_cmd.c | SRCS += order_cmd.c | ||||||
| SRCS += order_gui.c | SRCS += order_gui.c | ||||||
|  | SRCS += os_timer.c | ||||||
| SRCS += pathfind.c | SRCS += pathfind.c | ||||||
| SRCS += player_gui.c | SRCS += player_gui.c | ||||||
| SRCS += players.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); | void SetDebugString(const char *s); | ||||||
| const char *GetDebugString(void); | 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 */ | #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 */ | uint32 InteractiveRandom(void); /* Used for random sequences that are not the same on the other end of the multiplayer link */ | ||||||
| uint InteractiveRandomRange(uint max); | 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); | void SetDate(uint date); | ||||||
| /* facedraw.c */ | /* facedraw.c */ | ||||||
| void DrawPlayerFace(uint32 face, int color, int x, int y); | void DrawPlayerFace(uint32 face, int color, int x, int y); | ||||||
|   | |||||||
| @@ -339,6 +339,12 @@ SOURCE=.\ottdres.rc | |||||||
| # End Source File | # End Source File | ||||||
| # Begin Source File | # Begin Source File | ||||||
|  |  | ||||||
|  | SOURCE=.\os_timer.c | ||||||
|  | # End Source File | ||||||
|  | # Begin Source File | ||||||
|  |  | ||||||
|  | # Begin Source File | ||||||
|  |  | ||||||
| SOURCE=.\pathfind.c | SOURCE=.\pathfind.c | ||||||
| # End Source File | # End Source File | ||||||
| # Begin Source File | # Begin Source File | ||||||
|   | |||||||
| @@ -298,6 +298,9 @@ | |||||||
| 			<File | 			<File | ||||||
| 				RelativePath=".\ottdres.rc"> | 				RelativePath=".\ottdres.rc"> | ||||||
| 			</File> | 			</File> | ||||||
|  | 			<File | ||||||
|  | 				RelativePath=".\os_timer.c"> | ||||||
|  | 			</File> | ||||||
| 			<File | 			<File | ||||||
| 				RelativePath=".\pathfind.c"> | 				RelativePath=".\pathfind.c"> | ||||||
| 			</File> | 			</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}; | 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 */ | /* choose a track */ | ||||||
| static byte ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, TrackdirBits trackdirbits) | 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; | 	TrainTrackFollowerData fd; | ||||||
| 	uint best_track; | 	uint best_track; | ||||||
| #ifdef PF_BENCHMARK | #ifdef PF_BENCHMARK | ||||||
| 	int time = _rdtsc(); | 	TIC() | ||||||
| 	static float f; |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	assert((trackdirbits & ~0x3F) == 0); | 	assert((trackdirbits & ~0x3F) == 0); | ||||||
| @@ -2171,9 +2147,7 @@ static byte ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| #ifdef PF_BENCHMARK | #ifdef PF_BENCHMARK | ||||||
| 	time = _rdtsc() - time; | 	TOC("PF time = ", 1) | ||||||
| 	f = f * 0.99 + 0.01 * time; |  | ||||||
| 	printf("PF time = %d %f\n", time, f); |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	return best_track; | 	return best_track; | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								win32.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								win32.c
									
									
									
									
									
								
							| @@ -62,11 +62,6 @@ bool LoadLibraryList(Function proc[], const char* dll) | |||||||
| } | } | ||||||
|  |  | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
| #	ifdef _M_AMD64 |  | ||||||
| void* _get_save_esp(void); |  | ||||||
| uint64 _rdtsc(void); |  | ||||||
| #	endif |  | ||||||
|  |  | ||||||
| static const char *_exception_string; | static const char *_exception_string; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -594,6 +589,7 @@ static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep) | |||||||
| static void Win32InitializeExceptions(void) | static void Win32InitializeExceptions(void) | ||||||
| { | { | ||||||
| #ifdef _M_AMD64 | #ifdef _M_AMD64 | ||||||
|  | 	extern void *_get_save_esp(void); | ||||||
| 	_safe_esp = _get_save_esp(); | 	_safe_esp = _get_save_esp(); | ||||||
| #else | #else | ||||||
| 	_asm { | 	_asm { | ||||||
| @@ -603,7 +599,7 @@ static void Win32InitializeExceptions(void) | |||||||
|  |  | ||||||
| 	SetUnhandledExceptionFilter(ExceptionHandler); | 	SetUnhandledExceptionFilter(ExceptionHandler); | ||||||
| } | } | ||||||
| #endif | #endif /* _MSC_VER */ | ||||||
|  |  | ||||||
| static char *_fios_path; | static char *_fios_path; | ||||||
| static char *_fios_save_path; | static char *_fios_save_path; | ||||||
| @@ -1057,17 +1053,6 @@ static int ParseCommandLine(char *line, char **argv, int max_argc) | |||||||
| 	return n; | 	return n; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| #if defined(_MSC_VER) && !defined(_M_AMD64) |  | ||||||
| uint64 _declspec(naked) _rdtsc(void) |  | ||||||
| { |  | ||||||
| 	_asm { |  | ||||||
| 		rdtsc |  | ||||||
| 		ret |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| void CreateConsole(void) | void CreateConsole(void) | ||||||
| { | { | ||||||
| 	HANDLE hand; | 	HANDLE hand; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Darkvater
					Darkvater